Problem Description
XXX is very interested in algorithm. After learning the
Prim algorithm and Kruskal algorithm of minimum spanning tree, XXX finds that
there might be multiple solutions. Given an undirected weighted graph with n
(1<=n<=100) vertexes and m (0<=m<=1000) edges, he wants to know the
number of minimum spanning trees in the graph.
 
Input
There are no more than 15 cases. The input ends by 0 0
0.
For each case, the first line begins with three integers --- the above
mentioned n, m, and p. The meaning of p will be explained later. Each the
following m lines contains three integers u, v, w (1<=w<=10), which
describes that there is an edge weighted w between vertex u and vertex v( all
vertex are numbered for 1 to n) . It is guaranteed that there are no multiple
edges and no loops in the graph.
 
Output
For each test case, output a single integer in one line
representing the number of different minimum spanning trees in the graph.
The
answer may be quite large. You just need to calculate the remainder of the
answer when divided by p (1<=p<=1000000000). p is above mentioned, appears
in the first line of each test case.
Sample Input
5 10 12
2 5 3
2 4 2
3 1 3
3 4 2
1 2 3
5 4 3
5 1 3
4 1 1
5 3 3
3 2 3
0 0 0
 
Sample Output
4
 
Source
 
 
题意:求最小生成树的数量
 
矩阵树定理
 
回想 Kruskal算法,从小到大枚举边
当边权相等时,边随意排序
那么当权值为k的边全部枚举完后,点的联通情况F是固定的
也就是说权值都为k的边无论以什么顺序枚举,得到的生成树的形态不一,但联通情况F'和F相同
如果将加入最小生成树的 权值为1——k-1的边 和 对应的点 压缩成一个点,
所有权值为k 的边 的联通情况 是独立的
根据乘法原理
我们可以枚举权值k
计算此时形成F的方案数 
具体来说就是 枚举权值为k的边形成的连通块,用矩阵树定理算出每种连通块的方案数
累乘就是权值为k的边形成F的方案数
最后将所有权值为k的边的答案累乘
 
注意 并查集不要路径压缩
因为矩阵树定理需要每个点的度数

  1. #include<vector>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. int n,m,mod;
  7. int fa[],ka[];
  8. struct node
  9. {
  10. int u,v,w;
  11. }e[];
  12. int a[][];
  13. bool vis[];
  14. vector<int>g[];
  15. long long ans,C[][],t;
  16. bool cmp(node p,node q)
  17. {
  18. return p.w<q.w;
  19. }
  20. int find(int i,int *f) { return f[i]==i ? i : find(f[i],f); }
  21. bool init()
  22. {
  23. int u,v;
  24. scanf("%d%d%d",&n,&m,&mod);
  25. if(!n) return false;
  26. for(int i=;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
  27. return true;
  28. }
  29. long long det(int h)
  30. {
  31. long long s=;
  32. for(int i=;i<h;i++)
  33. {
  34. for(int j=i+;j<h;j++)
  35. while(C[j][i])
  36. {
  37. t=C[i][i]/C[j][i];
  38. for(int k=i;k<h;k++) C[i][k]=(C[i][k]-C[j][k]*t+mod)%mod;
  39. for(int k=i;k<h;k++) swap(C[i][k],C[j][k]);
  40. s=-s;
  41. }
  42. s=s*C[i][i]%mod;
  43. if(!s) return ;
  44. }
  45. return (s+mod)%mod;
  46. }
  47. void matrix_tree()
  48. {
  49. int len,u,v;
  50. for(int i=;i<=n;i++)
  51. if(vis[i])
  52. {
  53. g[find(i,ka)].push_back(i);
  54. vis[i]=false;
  55. }
  56. for(int i=;i<=n;i++)
  57. if(g[i].size())
  58. {
  59. memset(C,,sizeof(C));
  60. len=g[i].size();
  61. for(int j=;j<len;j++)
  62. for(int k=j+;k<len;k++)
  63. {
  64. u=g[i][j]; v=g[i][k];
  65. if(a[u][v])
  66. {
  67. C[k][j]=(C[j][k]-=a[u][v]);
  68. C[k][k]+=a[u][v]; C[j][j]+=a[u][v];
  69. }
  70. }
  71. ans=ans*det(g[i].size()-)%mod;
  72. for(int j=;j<len;j++) fa[g[i][j]]=i;
  73. }
  74. for(int i=;i<=n;i++)
  75. {
  76. g[i].clear();
  77. ka[i]=find(i,fa);
  78. }
  79. }
  80. void solve()
  81. {
  82. ans=;
  83. int u,v;
  84. memset(a,,sizeof(a));
  85. for(int i=;i<=n;i++) fa[i]=ka[i]=i;
  86. sort(e+,e+m+,cmp);
  87. for(int i=;i<=m+;i++)
  88. {
  89. if(e[i].w!=e[i-].w && i!= || i==m+) matrix_tree();
  90. u=find(e[i].u,fa); v=find(e[i].v,fa);
  91. if(u!=v)
  92. {
  93. vis[u]=vis[v]=true;
  94. ka[find(u,ka)]=find(v,ka);
  95. a[u][v]++; a[v][u]++;
  96. }
  97. }
  98. bool flag=true;
  99. for(int i=;i<n && flag;i++)
  100. if(find(i,fa)!=find(i+,fa)) flag=false;
  101. printf("%lld\n",flag ? ans%mod : );
  102. }
  103. int main()
  104. {
  105. while(init()) solve();
  106. }

 
 

hdu 4408 Minimum Spanning Tree的更多相关文章

  1. HDU 4408 Minimum Spanning Tree 最小生成树计数

    Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  2. 【HDU 4408】Minimum Spanning Tree(最小生成树计数)

    Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...

  3. 多校 HDU - 6614 AND Minimum Spanning Tree (二进制)

    传送门 AND Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 ...

  4. 数据结构与算法分析–Minimum Spanning Tree(最小生成树)

    给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree). 如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Mi ...

  5. Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA/(树链剖分+数据结构) + MST

    E. Minimum spanning tree for each edge   Connected undirected weighted graph without self-loops and ...

  6. CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge

    E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...

  7. Codeforces Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA链上最大值

    E. Minimum spanning tree for each edge 题目连接: http://www.codeforces.com/contest/609/problem/E Descrip ...

  8. MST(Kruskal’s Minimum Spanning Tree Algorithm)

    You may refer to the main idea of MST in graph theory. http://en.wikipedia.org/wiki/Minimum_spanning ...

  9. [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]

    这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...

随机推荐

  1. axis2调用webService几种方式

    主要有三种方式: 第一RPC方式,不生成客户端代码 第二,document方式,不生成客户端代码 第三,用wsdl2java工具,生成客户端方式调用 java代码: package samples.q ...

  2. POJ 3084 Panic Room(最大流最小割)

    Description You are the lead programmer for the Securitron 9042, the latest and greatest in home sec ...

  3. MFC常用数据类型

    下面这些是和Win32程序共同使用的数据类型BOOL:布尔值,取值为TRUE or FALSEBSTR:32-bit 字符指针BYTE:8-bit整数,未带正负号COLORREF:32-bit数值,代 ...

  4. 20172330 2017-2018-1 《Java程序设计》第四周学习总结

    20172330 2017-2018-1 <Java程序设计>第四周学习总结 教材学习内容总结 这一周的内容还是比较多的,而且很复杂,包含第四和第七章. 第四章向我们介绍了类结构的定义与概 ...

  5. 软工1816 · Alpha冲刺(1/10)

    团队信息 队名:爸爸饿了 组长博客:here 作业博客:here 组员情况 组员1(组长):王彬 过去两天完成了哪些任务 前后端代码规范统一 针对之前的alpha冲刺安排进一步细化任务卡片 明确apl ...

  6. [core python programming]chapter 7 programming MS office

    excel.pyw会有问题,解决如下: 因为python3x中没有tkMessageBox模块,Tkinter改成了tkinter你可以查看你的py当前支持的模块.在交互式命令行下输入>> ...

  7. iOS- 移动端Socket UDP协议广播机制的实现

    1.前言    什么是UDP协议广播机制?      举一个例, 例如在一群人群中,一个人要找张三,于是你向人群里大喊一声(广播):“谁是张三”   如果它是张三,它就会回应你,在网络中也是一样的. ...

  8. 自定义类属性设置及setter、getter方法的内部实现

    属性是可以说是面向对象语言中封装的一个体现,在自定义类中设置属性就相当于定义了一个私有变量.设置器(setter方法)以及访问器(getter方法),其中无论是变量的定义,方法的声明和实现都是系统自动 ...

  9. vc6.0批量加注释

    MATLAB批量加注释的方法非常简单明了,加注释是ctrl+R,去注释是ctrl+T 然后在VC中我对一条一条加注释的方法非常烦恼,我想也许会有简单的方法可以批量家注释.果然,先贴代码 '------ ...

  10. 内核blackhole

    1) 当arp表项不存在的时候,数据包等待表项存在了再发,还是直接把数据包给丢掉; 2)如果网络目的地址不可达,是在那一层把数据丢弃,再是路由层就判断还是arp层呢?