1016: [JSOI2008]最小生成树计数

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 6200  Solved: 2518
[Submit][Status][Discuss]

Description

  现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的
最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生
成树可能很多,所以你只需要输出方案数对31011的模就可以了。

Input

  第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整
数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,0
00。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。

Output

  输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。

Sample Input

4 6
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1

Sample Output

8
  1. /*
  2. * @Author: LyuC
  3. * @Date: 2017-09-07 21:48:20
  4. * @Last Modified by: LyuC
  5. * @Last Modified time: 2017-09-12 17:52:51
  6. */
  7. /*
  8. 题意:现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道
  9. 这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则
  10. 这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方
  11. 案数对31011的模就可以了。
  12.  
  13. 思路:每个最小生成树的相同权值的边数是相同的,并且连通性是相同的,只需要枚举每个
  14. 权值的相同连通性,并且是最小生成树中这个权值的个数的方案数,然后组合一下就行了
  15. */
  16. #include <bits/stdc++.h>
  17.  
  18. #define MAXN 105
  19. #define MAXM 1005
  20. #define mod 31011
  21.  
  22. using namespace std;
  23.  
  24. struct Edge{
  25. int u,v,w;
  26. bool operator < (const Edge & other) const{
  27. return w<other.w;
  28. }
  29. }edge[MAXM];
  30. vector<Edge>v[MAXM];
  31. int n,m;
  32. int x,y,z;
  33. int bin[MAXN];
  34. int root[MAXN];
  35. int vis[MAXM];//每种权值用到的数量
  36. int sum;
  37. int la;
  38. int pos;
  39. int res;
  40.  
  41. inline int findx(int x){
  42. int s=x;
  43. while(x!=bin[x])
  44. x=bin[x];
  45. bin[s]=x;
  46. return x;
  47. }
  48.  
  49. inline int Count(int x){
  50. int s=;
  51. while(x){
  52. if(x%)
  53. s++;
  54. x/=;
  55. }
  56. return s;
  57. }
  58.  
  59. inline void init(){
  60. for(int i=;i<=n;i++){
  61. bin[i]=i;
  62. root[i]=i;
  63. }
  64. memset(vis,,sizeof vis);
  65. for(int i=;i<MAXM;i++)
  66. v[i].clear();
  67. res=;
  68. pos=;
  69. sum=;
  70. }
  71.  
  72. int main(){
  73. // freopen("in.txt","r",stdin);
  74. scanf("%d%d",&n,&m);
  75. init();
  76. for(int i=;i<m;i++){
  77. scanf("%d%d%d",&x,&y,&z);
  78. edge[i].u=x;
  79. edge[i].v=y;
  80. edge[i].w=z;
  81. }
  82. sort(edge,edge+m);
  83. //处理每种权值需要的边数
  84. la=-;
  85. for(int i=;i<m;i++){
  86. if(edge[i].w!=la){
  87. la=edge[i].w;
  88. bool flag=false;
  89. for(int j=i;edge[j].w==la;j++){
  90. int fx=findx(edge[j].u);
  91. int fy=findx(edge[j].v);
  92. if(fx!=fy){
  93. flag=true;
  94. bin[fx]=fy;
  95. vis[pos]++;
  96. sum++;
  97. }
  98. v[pos].push_back(edge[j]);
  99. }
  100. pos++;
  101. }
  102. }
  103. if(sum!=n-){
  104. puts("");
  105. return ;
  106. }
  107. for(int i=;i<pos;i++){//枚举每个阶段用到权值的边
  108. if(vis[i]==) continue;
  109. int tol=(<<v[i].size());
  110. int cur=;//可以的方案
  111. for(int j=;j<tol;j++){
  112. if(Count(j)!=vis[i]) continue;
  113. bool flag=true;
  114. memcpy(bin,root,sizeof root);
  115. for(int k=;k<v[i].size();k++){
  116. if((j&(<<k))!=){//如果这条边存在
  117. int fx=findx(v[i][k].u);
  118. int fy=findx(v[i][k].v);
  119. if(fx==fy){
  120. flag=false;
  121. break;
  122. }else{
  123. bin[fx]=fy;
  124. }
  125. }
  126. }
  127. if(flag==true)
  128. cur++;
  129. }
  130. res=res*cur%mod;
  131. memcpy(bin,root,sizeof root);
  132. for(int j=;j<v[i].size();j++){
  133. int fx=findx(v[i][j].u);
  134. int fy=findx(v[i][j].v);
  135. if(fx!=fy){
  136. bin[fx]=fy;
  137. }
  138. }
  139. memcpy(root,bin,sizeof bin);
  140. }
  141. printf("%d\n",res%mod);
  142. return ;
  143. }

1016: [JSOI2008]最小生成树计数的更多相关文章

  1. BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

  2. 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

    1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...

  3. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

  4. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

    最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小 ...

  5. 【BZOJ】1016: [JSOI2008]最小生成树计数(kruskal+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1016 想也想不到QAQ 首先想不到的是:题目有说,具有相同权值的边不会超过10条. 其次:老是去想组 ...

  6. [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】

    题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...

  7. BZOJ.1016.[JSOI2008]最小生成树计数(Matrix Tree定理 Kruskal)

    题目链接 最小生成树有两个性质: 1.在不同的MST中某种权值的边出现的次数是一定的. 2.在不同的MST中,连接完某种权值的边后,形成的连通块的状态是一样的. \(Solution1\) 由这两个性 ...

  8. 大视野 1016: [JSOI2008]最小生成树计数(最小生成树)

    总结:此类题需要耐心观察规律,大胆猜想,然后证明猜想,得到有用的性质,然后解答. 简单的说:找隐含性质. 传送门:http://61.187.179.132/JudgeOnline/problem.p ...

  9. 1016: [JSOI2008]最小生成树计数 - BZOJ

    Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...

随机推荐

  1. Docker入门之三容器

    上一篇博客学习了下镜像,今天来学习容器.容器类似一个手机中的沙盒环境,用来运行app实例.和镜像一样也是对容器的创建.删除.导出等. 由于我买的参考书中的例子好多都是基于linux的,所以我将dock ...

  2. 使用VMware Workstation Pro 12 虚拟机安装Mac OS系统教程 全程图解

    导读:使用虚拟机安装Windows.Linux或者Ubuntu系统大家或许看了很多,但如何使用VMware Workstation Pro 12安装Mac OS,的确需要好好研究一番:否则无法下手,因 ...

  3. Java并发/多线程系列——初识篇

    回到过去,电脑有一个CPU,一次只能执行一个程序.后来多任务处理意味着计算机可以同时执行多个程序(AKA任务或进程).这不是真的"同时".单个CPU在程序之间共享.操作系统将在运行 ...

  4. 课程作业02(关于Java的几点讨论)

    ---恢复内容开始--- 1.一个Java类文件中真的只能有一个公有类吗? public class Test { public static void main(String[] args) { } ...

  5. selenium webdriver 启动三大浏览器Firefox,Chrome,IE

    selenium webdriver 启动三大浏览器Firefox,Chrome,IE 1.安装selenium 在联网的情况下,在Windows命令行(cmd)输入pip install selen ...

  6. Linux+Apache2.4+PHP5.6+MySQL5.6源码安装步骤

    一.安装Apache 若要安装apache服务器软件,需要安装以下几个依赖软件 apr-1.4.6.tar.gz 下载地址:http://apr.apache.org/ apr-util-1.4.1. ...

  7. 使用svn控制系统的优缺点和注意事项

    1.当无法连接到中央版本库的环境下,你无法提交代码,将代码加入版本控制.公司一般是局域网,所以使用环境问题不大. 2.svn的备份要备份所有代码数据以及所有更改的版本记录. 3.svn服务端运行方式: ...

  8. 基于LoadRunner11,以wifi热点方式录制APP脚本简单指导

    本想详细写下操作过程,但并不觉着十分必要,通过baidu或我要自学网均能找到相关资料,所以详细操作过程不再赘述,只是把过程中遇到的问题说明下解释下,让大家“录制APP”的路更平坦! 1.如何使用Loa ...

  9. android中跨线程向控件传值的问题

    activity.oncreate(bundle savedinstancestate)中创建一个handler类的实例, 在这个handler实例的handlemessage回调函数中调用更新界面显 ...

  10. 有趣的flash例子

    仓鼠 <object type="application/x-shockwave-flash" data="http://cdn.abowman.com/widge ...