uvalive 5834 Genghis Khan The Conqueror
题意:
给出一个图,边是有向的,现在给出一些边的变化的信息(权值大于原本的),问经过这些变换后,MST总权值的期望,假设每次变换的概率是相等的。
思路:
每次变换的概率相等,那么就是求算术平均。
首先求出最小生成树,若变换的边不在最小生成树上,那么就不用管;如果在,那么就需要求变换之后的MST的总权值,有两种情况,第一是继续使用变换后的边,还是MST,第二是放弃这条边,使用其它边构成MST。取两者中的最小值。
第二种情况需要较为深入的讨论,如何使得在较优的时间内找到一条边,使得这条边加入后还是MST。
放弃了一条边之后,MST就变成了两棵最小生成子树,那么要找的边实际就是两棵树之间的最短距离,就转化成了求两棵树之间的最短距离。
如何求两棵树的最短距离,树形dp,这个我也是看题解学习的Orz。具体的做法是每次用一个点作为根,在dfs的过程中,将每一条非树边对最短距离进行更新,这个最短距离对应的是去掉dfs中每一对点所连的边的形成的两棵子树。
看图
红色的是非树边,那么这条非树边就可以更新去掉点A与点B连的树边之后形成的两棵树的最小距离,也可以更新去掉点B与点C连的树边后形成的两棵树的最小距离。每次dfs访问n个点,n次dfs,所以复杂度为O(n^2)。

总复杂度为O(n^2)。
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std; const int N = ;
const int inf = 0x3f3f3f3f; int mp[N][N],pre[N];
bool used[N][N];
int dp[N][N];
int vis[N];
int d[N];
vector<int> g[N]; struct edge
{
int to,cost; edge(int a,int b)
{
to = a;
cost = b;
}
}; long long prim(int n)
{
memset(vis,,sizeof(vis));
memset(used,,sizeof(used));
//memset(path,0,sizeof(path)); for (int i = ;i < n;i++) g[i].clear(); vis[] = ;
d[] = ; for (int i = ;i < n;i++)
{
d[i] = mp[][i];
pre[i] = ;
} int ans = ; for (int i = ;i < n - ;i++)
{
int x;
int dis = inf; for (int j = ;j < n;j++)
{
if (!vis[j] && d[j] < dis)
{
x = j;
dis = d[j];
}
} vis[x] = ; used[x][pre[x]] = used[pre[x]][x] = ; g[x].push_back(pre[x]);
g[pre[x]].push_back(x); ans = ans + dis; for (int j = ;j < n;j++)
{
//if (vis[j] && j != x) path[x][j] = path[j][x] = max(dis,path[j][pre[x]]); if (!vis[j] && mp[x][j] < d[j])
{
d[j] = mp[x][j];
pre[j] = x;
}
}
} return ans;
} int dfs(int root,int u,int fa)
{
int s = inf; for (int i = ;i < g[u].size();i++)
{
int v = g[u][i]; if (v == fa) continue; int tmp = dfs(root,v,u); s = min(tmp,s); dp[u][v] = dp[v][u] = min(dp[u][v],tmp);
} if (root != fa)
s = min(s,mp[root][u]); return s;
} void solve(int n)
{
memset(dp,inf,sizeof(dp)); for (int i = ;i < n;i++)
{
dfs(i,i,-);
}
} int main()
{
int n,m; while (scanf("%d%d",&n,&m) != EOF)
{
if (m == && n == ) break; memset(mp,inf,sizeof(mp)); for (int i = ;i < n;i++)
{
g[i].clear();
} for (int i = ;i < m;i++)
{
int a,b,c; scanf("%d%d%d",&a,&b,&c); mp[a][b] = mp[b][a] = c; //G[a].push_back(edge(b,c));
//G[b].push_back(edge(a,c));
} int ans = prim(n); solve(n); //printf("ans = %d\n",ans); int q; scanf("%d",&q); long long res = ; for (int i = ;i < q;i++)
{
int x,y,c; scanf("%d%d%d",&x,&y,&c); if (!used[x][y]) res += ans;
else
{
long long tmp = (long long)ans + c - mp[x][y]; //printf("%d **\n",dp[x][y]); tmp = min(tmp,(long long)ans + dp[x][y] - mp[x][y]); res += tmp; //printf("%d %lld**\n",dp[x][y],tmp);
}
} printf("%.4f\n",(double) res / q);
} return ;
}
uvalive 5834 Genghis Khan The Conqueror的更多相关文章
- HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4126 Genghis Khan the Conqueror Time Limit: 10000/50 ...
- 刷题总结——Genghis Khan the Conqueror (hdu4126)
题目: Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元 ...
- 【Uvalive 5834】 Genghis Khan the Conqueror (生成树,最优替代边)
[题意] 一个N个点的无向图,先生成一棵最小生成树,然后给你Q次询问,每次询问都是x,y,z的形式, 表示的意思是在原图中将x,y之间的边增大(一定是变大的)到z时,此时最小生成数的值是多少.最后求Q ...
- UVA- 1504 - Genghis Khan the Conqueror(最小生成树-好题)
题意: n个点,m个边,然后给出m条边的顶点和权值,其次是q次替换,每次替换一条边,给出每次替换的边的顶点和权值,然后求出这次替换的最小生成树的值; 最后要你输出:q次替换的平均值.其中n<30 ...
- HDU 4126 Genghis Khan the Conqueror MST+树形dp
题意: 给定n个点m条边的无向图. 以下m行给出边和边权 以下Q个询问. Q行每行给出一条边(一定是m条边中的一条) 表示改动边权. (数据保证改动后的边权比原先的边权大) 问:改动后的最小生成树的权 ...
- HDU 4126 Genghis Khan the Conqueror (树形DP+MST)
题意:给一图,n个点,m条边,每条边有个花费,给出q条可疑的边,每条边有新的花费,每条可疑的边出现的概率相同,求不能经过原来可疑边 (可以经过可疑边新的花费构建的边),注意每次只出现一条可疑的边,n个 ...
- 「日常训练」 Genghis Khan the Conqueror(HDU-4126)
题意 给定\(n\)个点和\(m\)条无向边(\(n\le 3000\)),需要将这\(n\)个点连通.但是有\(Q\)次(\(Q\le 10^4\))等概率的破坏,每次破坏会把\(m\)条边中的某条 ...
- HDU-4126 Genghis Khan the Conqueror 树形DP+MST (好题)
题意:给出一个n个点m条边的无向边,q次询问每次询问把一条边权值增大后问新的MST是多少,输出Sum(MST)/q. 解法:一开始想的是破圈法,后来想了想应该不行,破圈法应该只能用于加边的情况而不是修 ...
- HDU4126Genghis Khan the Conqueror(最小生成树+并查集)
Genghis Khan the Conqueror Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 327680/327680 K ...
随机推荐
- 关于IM的一些思考与实践
上一篇简单的实现了一个聊天网页,但这个太简单,消息全广播,没有用户认证和已读未读处理,主要的意义是走通了websocket-sharp做服务端的可能性.那么一个完整的IM还需要实现哪些部分? 一.发消 ...
- 一篇关于Maven项目的jar包Shell启动脚本
使用Maven作为项目jar包依赖的管理,常常会遇到命令行启动,笔者也是哥菜鸟,在做微服务,以及服务器端开发的过程中,常常会遇到项目的启动需要使用main方法,笔者潜心的研究了很多博客,发现大多写的都 ...
- poj 1562 dfs
http://poj.org/problem?id=1562 #include<iostream> using namespace std; ,m=,sum=; ][]; ][]={-,, ...
- DotNetBar控件,superTabControl多文档界面(MDI)的风格、多Tab的创建方法
最近在做一个条码系统的项目,第一次用dotnetbar控件,,查找资料时看到伍老师一篇文章(链接),但是没有关于加载tab窗口的方法,自己摸索做了一个此类风格出来,并写了一个通用方法,供大家参考. 风 ...
- OpenGL学习笔记:第一个OpenGL程序
OpenGL环境搭建参考博客:VS2015下OpenGL库的配置. #include<GL\glew.h> #include<GLTools.h> #include<GL ...
- S2第一本书内测
<深入.NET平台和C#编程>内部测试题-笔试试卷 一 选择题 1) 以下关于序列化和反序列化的描述错误的是( C). a) 序列化是将对象的状态存储到特定存储介质中的过程 b) 二进制格 ...
- Web安全概述
互联网刚开始是安全的,但是伴随着黑客(Hacker)的诞生,互联网变得越来越不安全.任何一个事情都有两面性,黑客也有好有坏,好的黑客叫白帽子,坏的黑客叫黑帽子.与此同时,随着Web技术发展越来越成熟, ...
- struct_2拦截器与过滤器
这个为网上所剪切的知识点,仅为个人学习所用,无其他用途. 过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者 ...
- java中使用ReentrantLock锁中的Condition实现三个线程之间通信,交替输出信息
本文直接附上源代码,如下是自己写的一个例子 面试题需求: 使用Condition来实现 三个线程 线程1 线程2 线程3 三个交替输出 [按照 线程1(main)-->线程2-->线程3] ...
- Java基础学习笔记二十六 JDBC
什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使用SQL语句来操作数据库,J ...