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

HINT

Source

Solution

  最小生成树的性质:

  1. 对于每一个$MST$,每一种边权所使用的边数相同
  2. 所有$MST$中边权$\leq w$的边组成的图的连通性相同

  所以首先我们可以用$Kruskal$算出每一种边权使用的边数

  之后暴力枚举某种边权所使用的边

  因为最多只有$10$条边,所以时间可以接受,当没有这个限制条件时需要用到$Matrix$-$Tree$定理。对,你知道的,我不会这个

  顺便试着写了下冰炸鸡并查集按秩合并,稍微伪证了一下发现是$O(nlogn)$的,不过可以撤回?!好像又解锁了什么姿势

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. struct edge
  4. {
  5. int u, v, w, x;
  6. inline bool operator< (const edge &rhs) const
  7. {
  8. return x < rhs.x;
  9. }
  10. }e[];
  11. struct count
  12. {
  13. int l, r, use;
  14. }g[];
  15. int n, m, fa[], siz[];
  16.  
  17. int getfa(int x)
  18. {
  19. return fa[x] == x ? x : getfa(fa[x]);
  20. }
  21.  
  22. void link(int u, int v)
  23. {
  24. if(siz[u] > siz[v]) fa[v] = u, siz[u] += siz[v];
  25. else fa[u] = v, siz[v] += siz[u];
  26. }
  27.  
  28. bool Kruskal()
  29. {
  30. int cnt = , u, v;
  31. for(int i = ; i <= m; ++i)
  32. {
  33. u = getfa(e[i].u), v = getfa(e[i].v);
  34. if(u != v)
  35. {
  36. link(u, v);
  37. ++g[e[i].w].use;
  38. if(++cnt == n - ) return true;
  39. }
  40. }
  41. return false;
  42. }
  43.  
  44. int DFS(int w, int i, int k)
  45. {
  46. if(k == g[w].use) return ;
  47. if(i > g[w].r) return ;
  48. int ans = , u = getfa(e[i].u), v = getfa(e[i].v);
  49. if(u != v)
  50. {
  51. link(u, v);
  52. ans = DFS(w, i + , k + );
  53. fa[u] = u, fa[v] = v;
  54. }
  55. return ans + DFS(w, i + , k);
  56. }
  57.  
  58. int main()
  59. {
  60. int u, v, w, ans;
  61. cin >> n >> m;
  62. for(int i = ; i <= n; ++i)
  63. fa[i] = i, siz[i] = ;
  64. for(int i = ; i <= m; ++i)
  65. {
  66. cin >> u >> v >> w;
  67. e[i] = (edge){u, v, , w};
  68. }
  69. sort(e + , e + m + );
  70. w = ;
  71. for(int i = ; i <= m; ++i)
  72. if(e[i].x == e[i - ].x) e[i].w = w;
  73. else
  74. {
  75. g[w].r = i - ;
  76. e[i].w = ++w;
  77. g[w].l = i;
  78. }
  79. g[w].r = m;
  80. ans = Kruskal();
  81. for(int i = ; i <= n; ++i)
  82. fa[i] = i, siz[i] = ;
  83. for(int i = ; i <= w; ++i)
  84. {
  85. ans = ans * DFS(i, g[i].l, ) % ;
  86. for(int j = g[i].l; j <= g[i].r; ++j)
  87. {
  88. u = getfa(e[j].u), v = getfa(e[j].v);
  89. if(u != v) link(u, v);
  90. }
  91. }
  92. cout << ans << endl;
  93. return ;
  94. }

[BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)的更多相关文章

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

    1016: [JSOI2008]最小生成树计数 题目:传送门 题解: 神题神题%%% 据说最小生成树有两个神奇的定理: 1.权值相等的边在不同方案数中边数相等  就是说如果一种方案中权值为1的边有n条 ...

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

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

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

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

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

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

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

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

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

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

  7. [BZOJ1016][JSOI2008]最小生成树计数(结论题)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1016 分析: 首先有个性质:如果边集E.E'都可以表示一个图G的最小生成树(当然E和E ...

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

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

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

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

随机推荐

  1. Angular+ionic2+Echarts 实现图形制作,以饼图为例

    step1:添加插件echart; npm install echarts --save package.json文件中会在dependencies中添加echarts,如下图: step2:运行cm ...

  2. [Python Study Notes]匿名函数

    Python 使用 lambda 来创建匿名函数. lambda这个名称来自于LISP,而LISP则是从lambda calculus(一种符号逻辑形式)取这个名称的.在Python中,lambda作 ...

  3. visual studio code右侧的预览面板能关闭吗?

    https://segmentfault.com/q/1010000010082399   "editor.minimap.enabled":false

  4. wordpress配置固定链接nginx访问404问题解决方法

    WordPress支持使用固定链接,但是在ngnix环境下,访问页面后出现404, 其实官方是有文档说明的,需要单独写配置, 我这边配置的示例代码如下: server { listen       8 ...

  5. JAVAEE——BOS物流项目06:分页查询、分区导出Excel文件、定区添加、分页问题总结

    1 学习计划 1.分区组合条件分页查询 n 分区分页查询(没有过滤条件) n 分区分页查询(带有过滤条件) 2.分区导出 n 页面调整 n 使用POI将数据写到Excel文件 n 通过输出流进行文件下 ...

  6. 阿里云服务器 无法连接svn

    网上所说的在服务器中:1. 配置防火墙 2.svnserve.conf没配置好,3.svn客户端缓存,都进行排查处理,还是连接不上. 最后使用ip add 查看服务器网卡ip命令 发现无法看到当前服务 ...

  7. [记录]一则清理MySQL大表以释放磁盘空间的案例

    一则清理MySQL大表以释放磁盘空间的案例 一.基本情况: 1.dbtest库554G,先清理st_online_time_away_ds(37G)表的数据,保留半年的数据: 1)删除的数据:sele ...

  8. CentOS 挂载 cdrom, iso文件作为源

    在生产系统环境中的机器都没有连接互联网,因此都是使用本地源. 首先,需要将cdrom, 或 iso文件挂载到本地目录. 1.挂载光驱: 将cdrom 放入光驱. $  mkdir /media/cdr ...

  9. [翻译] .NET Core 2.1 Preview 1 发布

    [翻译] .NET Core 2.1 Preview 1 发布 原文: Announcing .NET Core 2.1 Preview 1 今天,我们宣布发布 .NET Core 2.1 Previ ...

  10. Centos下_MysqL5.7在使用mysqldump命令备份数据库报错:mysqldump: Got error: 1449: The user specified as a definer ('fk_system'@'localhost') does not exist when using LOCK TABLES

    在阿里云服务器增加一个shell脚本定时备份数据库脚本执行任务时,测试性的执行了备份命令,如下 [root@iZ2ze503xw2q1fftv5rhboZ mysql_bak]# /usr/local ...