题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4126

题目意思:

给一图,n个点,m条边,每条边有个花费,给出q条可疑的边,每条边有新的花费,每条可疑的边出现的概率相同,求不能经过原来可疑边(可以经过可疑边新的花费构建的边),注意每次只出现一条可疑的边,n个点相互连通的最小花费的期望。

解题思路:

树形dp+MST。

先用kruskal算法找到最小生成树,并求出总花费sum.

再以枚举n个点,依次作为树根dfs,dp[i][j]表示<i,j>为最小生成树上的边,且去掉该边后,包括点i的连通块中的点集A到包括点j的连通块点集B的最小距离。

对于根节点为ro,边为<i,j>的dp[i][j]=min(以j节点为根的子树到ro的最短距离,dp[i][j]).

如下图所示:

以右边点集为子树求出左边点集中每个点作为树根时到all的最小距离。其实对于上面那条边,只用枚举ro个点就行了,但是不好确定每条边的ro集,所以枚举n个点,作为ro,然后dfs,最每条边更新一次,时间复杂度为o(n^2)可以接受。

代码:

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<string>
  6. #include<cstring>
  7. #include<algorithm>
  8. #include<vector>
  9. #include<map>
  10. #include<set>
  11. #include<stack>
  12. #include<list>
  13. #include<queue>
  14. #include<ctime>
  15. #define eps 1e-6
  16. #define INF 0x3f3f3f3f
  17. #define PI acos(-1.0)
  18. #define ll __int64
  19. #define lson l,m,(rt<<1)
  20. #define rson m+1,r,(rt<<1)|1
  21. #pragma comment(linker, "/STACK:1024000000,1024000000")
  22. using namespace std;
  23.  
  24. #define Maxn 3300
  25. struct Edge
  26. {
  27. int a,b,c;
  28. }edge[Maxn*Maxn]; //保存边的信息
  29.  
  30. int dis[Maxn][Maxn]; //原始距离
  31. bool hav[Maxn][Maxn]; //是否为最小生成树上的边
  32. int fa[Maxn],dp[Maxn][Maxn];//dp[i][j]表示<i,j>为最小生成树上的边,且去掉该边后,包括点i的连通块中的点集A到包括点j的连通块点集B的最小距离。
  33. int n,m,cnt;
  34. ll sum;
  35.  
  36. int find(int x) //并查集
  37. {
  38. int tmp=x;
  39. while(x!=fa[x])
  40. x=fa[x];
  41. while(fa[tmp]!=x)
  42. {
  43. int tt=fa[tmp];
  44. fa[tmp]=x;
  45. tmp=tt;
  46. }
  47. return x;
  48. }
  49. bool cmp(struct Edge a,struct Edge b)
  50. {
  51. return a.c<b.c;
  52. }
  53. struct EE //构建最小生成树
  54. {
  55. int v;
  56. struct EE * next;
  57. }ee[Maxn<<1],*head[Maxn<<1];
  58.  
  59. void add(int a,int b)
  60. {
  61. ++cnt;
  62. ee[cnt].v=b;
  63. ee[cnt].next=head[a];
  64. head[a]=&ee[cnt];
  65. }
  66.  
  67. void kruskal() //克鲁斯卡尔算法求最小生成树
  68. {
  69. sum=0;
  70. cnt=0;
  71. for(int i=1;i<=m;i++)
  72. {
  73. int a=find(edge[i].a),b=find(edge[i].b);
  74. if(a!=b)
  75. {
  76. fa[b]=edge[i].a;
  77. sum+=edge[i].c;
  78. hav[edge[i].a][edge[i].b]=hav[edge[i].b][edge[i].a]=true;
  79. add(edge[i].a,edge[i].b); //建树
  80. add(edge[i].b,edge[i].a);
  81. }
  82. }
  83. }
  84. int dfs(int ro,int fa,int cur,int dep) //表示以cur作为当前子树根中所有子树节点到总根ro的最短距离
  85. {
  86. struct EE * p=head[cur];
  87. int mi=INF;
  88.  
  89. if(dep!=1) //不为树根的儿子
  90. mi=dis[cur][ro];
  91. while(p)
  92. {
  93. int v=p->v;
  94. if(v!=fa)
  95. {
  96. int tt=dfs(ro,cur,v,dep+1);
  97. mi=min(mi,tt);
  98. dp[cur][v]=dp[v][cur]=min(dp[v][cur],tt);//更新当前边
  99. }
  100. p=p->next;
  101. }
  102. return mi;
  103.  
  104. }
  105.  
  106. int main()
  107. {
  108. // printf("%d\n",INF);
  109. while(scanf("%d%d",&n,&m)&&n+m)
  110. {
  111. memset(dis,INF,sizeof(dis));
  112. for(int i=1;i<=m;i++)
  113. {
  114. int a,b,c;
  115. scanf("%d%d%d",&a,&b,&c);
  116. edge[i].a=a,edge[i].b=b,edge[i].c=c;
  117. dis[a][b]=dis[b][a]=c;
  118. }
  119. sort(edge+1,edge+m+1,cmp);
  120. for(int i=0;i<n;i++)
  121. fa[i]=i;
  122. memset(hav,false,sizeof(hav));
  123. memset(head,NULL,sizeof(head));
  124. kruskal();
  125.  
  126. memset(dp,INF,sizeof(dp));
  127. for(int i=0;i<n;i++) //以每个点最为树根,对每条边更新n次
  128. dfs(i,i,i,0);
  129.  
  130. ll ans=0;
  131. int q;
  132. scanf("%d",&q);
  133. for(int i=1;i<=q;i++)
  134. {
  135. int a,b,c;
  136. scanf("%d%d%d",&a,&b,&c);
  137. if(hav[a][b]) //是最小生成树上的边
  138. {
  139. int tt=min(dp[a][b],c); //要么用新边,要么用不是最小生成树上的边
  140. ans=ans+sum-dis[a][b]+tt;
  141. }
  142. else //不是最小生成树上的边,直接用最小生成树
  143. ans=ans+sum;
  144. // printf("*%lf\n",ans);
  145. }
  146. printf("%.4f\n",ans*1.0/q);
  147. }
  148. return 0;
  149. }

树形dp+MST-hdu-4126-Genghis Khan the Conqueror的更多相关文章

  1. HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4126 Genghis Khan the Conqueror Time Limit: 10000/50 ...

  2. HDU 4126 Genghis Khan the Conqueror MST+树形dp

    题意: 给定n个点m条边的无向图. 以下m行给出边和边权 以下Q个询问. Q行每行给出一条边(一定是m条边中的一条) 表示改动边权. (数据保证改动后的边权比原先的边权大) 问:改动后的最小生成树的权 ...

  3. HDU 4126 Genghis Khan the Conqueror (树形DP+MST)

    题意:给一图,n个点,m条边,每条边有个花费,给出q条可疑的边,每条边有新的花费,每条可疑的边出现的概率相同,求不能经过原来可疑边 (可以经过可疑边新的花费构建的边),注意每次只出现一条可疑的边,n个 ...

  4. HDU-4126 Genghis Khan the Conqueror 树形DP+MST (好题)

    题意:给出一个n个点m条边的无向边,q次询问每次询问把一条边权值增大后问新的MST是多少,输出Sum(MST)/q. 解法:一开始想的是破圈法,后来想了想应该不行,破圈法应该只能用于加边的情况而不是修 ...

  5. 刷题总结——Genghis Khan the Conqueror (hdu4126)

    题目: Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元 ...

  6. UVA- 1504 - Genghis Khan the Conqueror(最小生成树-好题)

    题意: n个点,m个边,然后给出m条边的顶点和权值,其次是q次替换,每次替换一条边,给出每次替换的边的顶点和权值,然后求出这次替换的最小生成树的值; 最后要你输出:q次替换的平均值.其中n<30 ...

  7. uvalive 5834 Genghis Khan The Conqueror

    题意: 给出一个图,边是有向的,现在给出一些边的变化的信息(权值大于原本的),问经过这些变换后,MST总权值的期望,假设每次变换的概率是相等的. 思路: 每次变换的概率相等,那么就是求算术平均. 首先 ...

  8. 【Uvalive 5834】 Genghis Khan the Conqueror (生成树,最优替代边)

    [题意] 一个N个点的无向图,先生成一棵最小生成树,然后给你Q次询问,每次询问都是x,y,z的形式, 表示的意思是在原图中将x,y之间的边增大(一定是变大的)到z时,此时最小生成数的值是多少.最后求Q ...

  9. 「日常训练」 Genghis Khan the Conqueror(HDU-4126)

    题意 给定\(n\)个点和\(m\)条无向边(\(n\le 3000\)),需要将这\(n\)个点连通.但是有\(Q\)次(\(Q\le 10^4\))等概率的破坏,每次破坏会把\(m\)条边中的某条 ...

  10. 【树形DP】 HDU 2412 Party at Hali-Bula

    给出根节点(BOSS) 然后还有N-1个边  A B 由B指向A (B为A 的上司) 每次仅仅能选择这个关系中的当中一个 求最多选几个点 而且输出是不是唯一的 重点推断是否唯一: 1.若下属不去和去都 ...

随机推荐

  1. 妹子图太多怎么看才好,Swing来支招

    近期事少,翻开非常久曾经写的小程序,创意倒是尚可,代码写的却比較基础,非常多东西没有实现,略改了改形成了如今的模样,如今大家都忙着大数据,中间件,web开发,偶尔看看Java Swing的作品,也许能 ...

  2. 详解Android Handler的使用-别说你不懂handler(转)

    我们进行Android开发时,Handler可以说是使用非常频繁的一个概念,它的用处不言而喻.本文就详细介绍Handler的基本概念和用法. Handler的基本概念         Handler主 ...

  3. 安装Stomp扩展时错误提示error: 'zend_class_entry' has no member named 'default_properties'

    在安装stomp扩展时, 有这样的提示 error: 'zend_class_entry' has no member named 'default_properties' 交待下安装上下文, sto ...

  4. asp.net错误日志写入

    当我们一个web项目开发已完成,测试也通过了后,就把他放到网上去,但是,bug是测不完的,特别是在一个大的网络环境下.那么,我们就应该记录这些错误,然后改正.这里,我的出错管理页面是在global.a ...

  5. editplus双击单词语法高亮显示设置

    view=>Word Highlighting

  6. c# 学习笔记(二)

    c#3.0 新特性  扩展方法 扩展方法允许编写和声明它的类之外的关联类的方法 用于没有源代码或者类是密封的,需要给类扩展新方法时 1.扩展方法必须被声明为static2.扩展方法声明所在的类必须被声 ...

  7. EBS基础—表的后缀

    1._ALL或无后缀:基表,所有对数据操作最终都是对基表的操作,表包含所有不同经营单位的信息,多组织环境. 2._B/_T:也是一种基表.一些数据和验证存储在此表中. 3._TL:语言的基表,TL表支 ...

  8. 对C#泛型实例化对像--转

    最近在编写一套开发框架结构主要应用.Net 3.5以上的框架开发与应用.在此框架中应用了较多的泛型.下面来讲讲对泛型的实例化,以代码为例,如: public class A { } public cl ...

  9. 设置windows窗口ICON 【windows 编程】【API】【原创】

    1. ICON介绍 最近开始接触windows 编程,因此将自己所接触的一些零散的知识进行整理并记录.本文主要介绍了如何更改windows对话框窗口的ICON图标.这里首先介绍一下windows IC ...

  10. 『重构--改善既有代码的设计』读书笔记----Replace Method with Method Object

    有时候,当你遇到一个大型函数,里面的临时变量和参数多的让你觉得根本无法进行Extract Method.重构中也大力的推荐短小函数的好处,它所带来的解释性,复用性让你收益无穷.但如果你遇到上种情况,你 ...