【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1016

【题意】

【题解】

  1. /*
  2. 两个最小生成树T和T';
  3. 它们各个边权的边的数目肯定是一样的;
  4. 且相同边权的边;
  5. 那些边所形成的联通性是一样的;
  6. 可以考虑T和T'的形成;
  7. 比如说一开始
  8. T和T'都是空的;
  9. 然后把边按边权从小到大排序后
  10. 找到的第一种边权的边权为
  11. v1
  12. 且bian[left..right]都是这种边权的边;
  13. 然后假设T是我们正常用卡鲁斯卡尔算法搞出来的最小生成树;
  14. 那么T在这个阶段肯定会在这right-left+1条边中选择x条边;
  15. 那么这个时候我们再想想T'要怎么选?
  16. 假设我们选y条边
  17. 这里我们分类讨论一下
  18. 假如y>x,
  19. 这种情况是不可能的;
  20. 因为如果y可以大于x;
  21. 那就说明T还可以再加一条边权最小的边v1联通更多的分量;
  22. 而我们在做克鲁斯卡尔的时候已经保证了不能添加更多的分量;
  23. 所以可以排除;
  24. 假如y<x
  25. 这种情况也是不可能的;
  26. 假设我们少选了一条边
  27. 那么这条边链接的两个分量必然是要用更大的边权来链接;
  28. 这就不符合最小生成树了;
  29. 所也可以排除;
  30. 综上可知
  31. x==y;
  32. 这里所选的y条边的各个节点的连通性必然和x条边的联通性一样;
  33. 因为如果不一样的话,
  34. 那么哪里不一样呢??
  35. ->假设在T'中相对于T有两个分量没有连通在一起,那么你可以选择T中连接这两个分量的
  36. 边啊。而且因为是升序排的,所以肯定连了更优啊;
  37. 但是显然不可能再有这样的连法了,因为T是正确的最小生成树;
  38. 你如果能找到这样的连法的话,就说明T是不正确的了;
  39. 这就矛盾了;
  40. 根据上面的推导可知;
  41. 每个最小生成树;
  42. 出现的不同边权的种类是一样的,且各种边权的数目是确定的;
  43. 而且只要边权的数目确定了,这个边权造成的连通性的变化都是一样的;
  44. 所以我们只要枚举对于每一种边权,可以用哪些连着不同节点的边,但边权和它相同的边交换一下
  45. 一开始做的最小生成树的边就好了;
  46. 比如第i种边权的边v[i],出现的次数为numv[i];
  47. 然后在用克鲁斯卡尔算法算出的最小生成树中v[i]出现的次数为k;
  48. 则从这numv[i]条边中选出k条边来,看看是不是这k条边中每条边都能对联通量贡献;(如果有一条边在做
  49. 的过程中边的两段链接的联通量已经是在一起的了,就退出,表示不行);
  50. 因为要回溯,所以这里的并查集不能加状态压缩。
  51. 当然n也不大就是了;
  52. 因为有说同边权的边的数目不超过10,所以2^10是可以接受的.
  53. 搜一波;
  54. 然后用乘法原理乘起来就好;
  55. */

【完整代码】

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define lson l,m,rt<<1
  4. #define rson m+1,r,rt<<1|1
  5. #define LL long long
  6. #define rep1(i,a,b) for (int i = a;i <= b;i++)
  7. #define rep2(i,a,b) for (int i = a;i >= b;i--)
  8. #define mp make_pair
  9. #define pb push_back
  10. #define fi first
  11. #define se second
  12. #define rei(x) scanf("%d",&x)
  13. #define rel(x) scanf("%lld",&x)
  14. typedef pair<int, int> pii;
  15. typedef pair<LL, LL> pll;
  16. const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
  17. const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
  18. const double pi = acos(-1.0);
  19. const int M = 1100;
  20. const int N = 110;
  21. const int MOD = 31011;
  22. struct abc
  23. {
  24. int x, y,z;
  25. };
  26. int n, m,f[N],tot = 0,tot1 = 0,num[M],sum = 0,ans = 1;
  27. abc bian[M];
  28. bool cmp1(abc a, abc b)
  29. {
  30. return a.z < b.z;
  31. }
  32. int ff(int x)
  33. {
  34. if (f[x] == x) return x;
  35. else
  36. return ff(f[x]);
  37. }
  38. void dfs(int l, int r, int now)
  39. {
  40. if (now == num[tot])
  41. {
  42. sum++;
  43. return;
  44. }
  45. if (l > r) return;
  46. int x = bian[l].x, y = bian[l].y;
  47. int r1 = ff(x), r2 = ff(y);
  48. //这里f[r1]==r1,f[r2]==r2;
  49. if (r1 != r2)
  50. {
  51. f[r1] = r2;
  52. dfs(l + 1, r, now + 1);
  53. f[r1] = r1, f[r2] = r2;
  54. }
  55. dfs(l + 1, r, now);
  56. }
  57. int main()
  58. {
  59. //freopen("F:\\rush.txt", "r", stdin);
  60. rei(n), rei(m);
  61. rep1(i, 1, m)
  62. rei(bian[i].x), rei(bian[i].y), rei(bian[i].z);
  63. sort(bian + 1, bian + 1 + m,cmp1);
  64. rep1(i, 1, n)
  65. f[i] = i;
  66. rep1(i, 1, m)
  67. {
  68. int l = i, r = i;
  69. while (r + 1 <= m && bian[r + 1].z == bian[l].z) r++;
  70. tot1++;
  71. rep1(j, l, r)
  72. {
  73. int x = bian[j].x, y = bian[j].y;
  74. int r1 = ff(x), r2 = ff(y);
  75. if (r1 != r2)
  76. {
  77. f[r1] = r2;
  78. tot++;
  79. num[tot1]++;
  80. }
  81. }
  82. i = r;
  83. }
  84. if (tot != n - 1)
  85. return puts("0"), 0;
  86. rep1(i, 1, n)
  87. f[i] = i;
  88. tot = 0;
  89. rep1(i, 1, m)
  90. {
  91. int l = i, r = i;
  92. while (r + 1 <= m && bian[r + 1].z == bian[l].z) r++;
  93. tot++;
  94. if (num[tot] == 0)
  95. {
  96. i = r;//。。。。。。bug点
  97. continue;
  98. }
  99. sum = 0;
  100. dfs(l, r, 0);
  101. ans = (ans*sum) % MOD;
  102. rep1(j, l, r)
  103. {
  104. int r1 = ff(bian[j].x), r2 = ff(bian[j].y);
  105. if (r1 != r2)
  106. f[r1] = r2;
  107. }
  108. i = r;
  109. }
  110. printf("%d\n", ans);
  111. return 0;
  112. }

【BZOJ 1016】[JSOI2008]最小生成树计数(搜索+克鲁斯卡尔)的更多相关文章

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

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

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

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

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

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

  4. bzoj 1016: [JSOI2008]最小生成树计数【dfs+克鲁斯卡尔】

    有一个性质就是组成最小生成树总边权值的若干边权总是相等的 这意味着按边权排序后在权值相同的一段区间内的边能被选入最小生成树的条数是固定的 所以先随便求一个最小生成树,把每段的入选边数记录下来 然后对于 ...

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

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

  6. bzoj 1016 [JSOI2008]最小生成树计数——matrix tree(相同权值的边为阶段缩点)(码力)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 就是缩点,每次相同权值的边构成的联通块求一下matrix tree.注意gauss里的 ...

  7. BZOJ 1016 [JSOI2008]最小生成树计数 ——Matrix-Tree定理

    考虑从小往大加边,然后把所有联通块的生成树个数计算出来. 然后把他们缩成一个点,继续添加下一组. 最后乘法原理即可. 写起来很恶心 #include <queue> #include &l ...

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

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

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

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

随机推荐

  1. WEB前端--深入进去

    在网站开发这条道路上做专做精,一个专题一个专题的深入探索,一个盲区一个盲区的理解和记忆,终有大成的那一天的.

  2. Java核心技术 卷Ⅰ 基础知识(4)

    第六章 接口与内部类 接口 特性 接口与抽象类 对象克隆 接口与回调 内部类 使用内部类访问对象状态 内部类的特殊语法规则 局部内部类 匿名内部类 静态内部类 代理 Class[] in=new Cl ...

  3. 1.Python字符编码

    1.编码简介 编码的种类情况 ASCII 占1个字节,只支持英文 GB2312 占2个字节,支持6700+汉字 GBK GB2312的升级版,支持21000+汉字 ks_c_5601-1987 韩国编 ...

  4. UVA 11584 - Partitioning by Palindromes DP

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  5. springboot入门(三)-- springboot集成mybatis及mybatis generator工具使用

    前言 mybatis是一个半自动化的orm框架,所谓半自动化就是mybaitis只支持数据库查出的数据映射到pojo类上,而实体到数据库的映射需要自己编写sql语句实现,相较于hibernate这种完 ...

  6. codeforces Round 246 D. Prefixes and Suffixes (后缀数组 || KMP)

    题目大意: 求一个子串,子串既是前缀又是后缀. 然后再求出它在整个串中出现的次数. 思路分析: 能够非常easy想到怎样推断一个串既是前缀又是后缀. 仅仅须要它与 sa[0] 的lcp 等于 整个串的 ...

  7. window.print()打印网页(一)

    有时候需要将网页内容打印到纸上,最简单的一种方法是用window对象的print方法. window.print()默认打印当前网页的所有部分.(除了背景,默认打印都是白底黑字,如果有特别的设置 要另 ...

  8. [Err] 1136 - Column count doesn&#39;t match value count at row 1

    1 错误描写叙述 [Err] 1136 - Column count doesn't match value count at row 1 Procedure execution failed 113 ...

  9. 页面中如何引用外部的HTML(四种方法)

    页面中如何引用外部的HTML(四种方法) 一.总结 一句话总结:a.iframe标签        b.ajax引入代码片段        c.link import的方法导入        d.re ...

  10. 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包

    前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”) ...