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

题目:传送门

题解:

   神题神题%%%

   据说最小生成树有两个神奇的定理:

   1、权值相等的边在不同方案数中边数相等

      就是说如果一种方案中权值为1的边有n条

      那么在另一种方案中权值为1的边也一定有n条

   2、如果边权为1的边连接的点是x1,x2,x3

      那么另一种方案中边权为1的边连接的也一定是x1,x2,x3

  

   如果知道了这两条定理那就很好做了啊:

   因为等权边的条数一定,那么我们就可以预处理求出不同边权的边的条数

   题目很人道的保证了边权相同的边不会超过10条,那就可以光明正大的递归得出方案数了啊

  

   接下来就要利用定理2了:

   因为连接的点总是不变的,所以每一次选边是没有影响的,那么递归求出每一种权值边的方案数之后用乘法原理乘起来就ok

代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<algorithm>
  6. #define mod 31011
  7. #define qread(x) x=read()
  8. using namespace std;
  9. inline int read()
  10. {
  11. int f=,x=;char ch;
  12. while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
  13. while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
  14. return f*x;
  15. }
  16. struct node
  17. {
  18. int x,y,c,next;
  19. }a[];int n,m,sum;
  20. int fa[];
  21. int findfa(int x)
  22. {
  23. if(x==fa[x])return x;
  24. return findfa(fa[x]);
  25. }
  26. bool cmp(node n1,node n2)
  27. {
  28. return n1.c<n2.c;
  29. }
  30. int d[],s[];
  31. void dfs(int k,int t,int i)//当前选的是第k种边,已经选了t条,当前位置为第i条边
  32. {
  33. if(i==s[k]+)
  34. {
  35. if(t==d[k])
  36. sum++,sum%=mod;
  37. return ;
  38. }
  39. int fx=findfa(a[i].x),fy=findfa(a[i].y);
  40. if(fx!=fy)
  41. {
  42. fa[fx]=fy;
  43. dfs(k,t+,i+);
  44. fa[fx]=fx;
  45. }
  46. dfs(k,t,i+);
  47. }
  48. int main()
  49. {
  50. qread(n);qread(m);
  51. for(int i=;i<=m;i++){qread(a[i].x);qread(a[i].y);qread(a[i].c);}
  52. sort(a+,a+m+,cmp);
  53. for(int i=;i<=n;i++)fa[i]=i;
  54. int k=,t=;memset(d,,sizeof(d));memset(s,,sizeof(s));
  55. for(int i=;i<=m;i++)
  56. {
  57. int fx=findfa(a[i].x),fy=findfa(a[i].y);
  58. if(a[i].c!=a[i-].c)s[k]=i-,k++;//记录第k种边的最后一个位置
  59. if(fx!=fy)
  60. {
  61. fa[fx]=fy;
  62. t++;d[k]++;
  63. }
  64. }
  65. s[k]=m;
  66. if(t!=n-){printf("0\n");return ;}
  67. for(int i=;i<=n;i++)fa[i]=i;
  68. int ans=;
  69. for(int i=;i<=k;i++)
  70. {
  71. sum=;
  72. dfs(i,,s[i-]+);
  73. ans=(ans*sum)%mod;
  74. for(int j=s[i-]+;j<=s[i];j++)
  75. {
  76. int fx=findfa(a[j].x),fy=findfa(a[j].y);
  77. if(fx!=fy)fa[fx]=fy;
  78. }
  79. }
  80. printf("%d\n",ans);
  81. return ;
  82. }

bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)的更多相关文章

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

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

  2. [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)

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

  3. [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)

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

  4. bzoj1016 [JSOI2008]最小生成树计数——Kruskal+矩阵树定理

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 从 Kruskal 算法的过程来考虑产生多种方案的原因,就是边权相同的边有一样的功能, ...

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

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

  6. bzoj1016 [JSOI2008]最小生成树计数

    1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3517  Solved: 1396[Submit][St ...

  7. bzoj1016: [JSOI2008]最小生成树计数(kruskal+dfs)

    一直以为这题要martix-tree,实际上因为有相同权值的边不大于10条于是dfs就好了... 先用kruskal求出每种权值的边要选的次数num,然后对于每种权值的边2^num暴搜一下选择的情况算 ...

  8. BZOJ1016:[JSOI2008]最小生成树计数(最小生成树,DFS)

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

  9. bzoj1016/luogu4208 最小生成树计数 (kruskal+暴搜)

    由于有相同权值的边不超过10条的限制,所以可以暴搜 先做一遍kruskal,记录下来每个权值的边使用的数量(可以离散化一下) 可以证明,对于每个权值,所有的最小生成树中选择的数量是一样的.而且它们连成 ...

随机推荐

  1. if判断语句

     6)if判断语句   if ... then   else   end if;     if ... then   elsif ... then   elsif ... then   else   ...

  2. org.apache.hadoop.ipc.Client: Retrying connect to server

    这个问题导致jps查看结点进程时发现找不到NodeManager或一段时间后消失,网上查找了很多博客,因hadoop版本不一样且出错的原因也可能不同,所以找了老半天. 步骤:jps --> 看l ...

  3. 使用excel进行数据挖掘(3)----类别检測

    使用excel进行数据挖掘(3)----类别检測 在配置环境后,能够使用excel进行数据挖掘. 环境配置问题可參阅: http://blog.csdn.net/xinxing__8185/artic ...

  4. ZOJ 3435

    求(1,1,1)至(x,y,z)的互质个数. 即求(0,0,0)到(x-1,y-1,z-1)互质个数. 依然如上题那样做.但很慢...好像还有一个分块的思想,得学学. #include <ios ...

  5. Nginx系列(四)--工作原理

    上篇文章介绍了Nginx框架的设计之管理进程以及多个工作进程的设计.master进程用来管理通过fork子进程与子进程通信.子进程通过处理进程信号接到master的通信去处理请求. Nginx工作原理 ...

  6. Aizu - 2306 Rabbit Party (DFS图论)

    G. Rabbit Party Time Limit: 5000ms Case Time Limit: 5000ms Memory Limit: 65536KB 64-bit integer IO f ...

  7. ZooKeeper伪集群环境搭建

    1.从官网下载程序包. 2.解压. [dev@localhost software]$ tar xzvf zookeeper-3.4.6.tar.gz 3.进入zookeeper文件夹后创建data文 ...

  8. etxjs

    序言 编辑 功能丰富,无人能出其右. 无论是界面之美,还是功能之强,ext的表格控件都高居榜首. 单选行,多选行,高亮显示选中的行,拖拽改变列宽度,按列排序,这些基本功能ExtJS轻量级实现. 自动生 ...

  9. 12:Challenge 5(线段树区间直接修改)

    总时间限制:  10000ms 单个测试点时间限制:  1000ms 内存限制:  262144kB 描述 给一个长为N的数列,有M次操作,每次操作是以下两种之一: (1)将某连续一段同时改成一个数 ...

  10. 10:Challenge 3(树状数组直接修改)

    总时间限制:  10000ms 单个测试点时间限制:  1000ms 内存限制:  262144kB 描述 给一个长为N的数列,有M次操作,每次操作是以下两种之一: (1)修改数列中的一个数 (2)求 ...