1016: [JSOI2008]最小生成树计数 - BZOJ
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,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过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的边在一棵最小生成树里造成连通情况是(1,2)(3,4),在另一棵最小生成树里造成的连通情况是(1,4)(2,3)
那我们可以合并它们用权值为1的边做到(1,2,3,4),来替换一条权值大于1的边,得到一颗权值更小的树
证毕.
所以我们记录每种权值的边所造成的连通情况记录下来,每个权值做一遍,乘起来就是答案(注意判断无解的情况)
1 const 2 maxn=105; 3 maxm=1010; 4 h=31011; 5 var 6 ans,n,m,l:longint; 7 u,v,w:array[0..maxm]of longint; 8 a:array[0..10,0..1024]of longint; 9 10 procedure swap(var x,y:longint); 11 var 12 t:longint; 13 begin 14 t:=x;x:=y;y:=t; 15 end; 16 17 procedure sort(l,r:longint); 18 var 19 i,j,y:longint; 20 begin 21 i:=l; 22 j:=r; 23 y:=w[(l+r)>>1]; 24 repeat 25 while w[i]<y do 26 inc(i); 27 while w[j]>y do 28 dec(j); 29 if i<=j then 30 begin 31 swap(u[i],u[j]); 32 swap(v[i],v[j]); 33 swap(w[i],w[j]); 34 inc(i); 35 dec(j); 36 end; 37 until i>j; 38 if i<r then sort(i,r); 39 if j>l then sort(l,j); 40 end; 41 42 function bit(x:longint):longint; 43 begin 44 if x=0 then exit(0); 45 exit(bit(x-(x and -x))+1); 46 end; 47 48 procedure init; 49 var 50 i,k:longint; 51 begin 52 read(n,m); 53 for i:=1 to m do 54 read(u[i],v[i],w[i]); 55 sort(1,m); 56 for i:=0 to 1023 do 57 begin 58 k:=bit(i); 59 inc(a[k,0]); 60 a[k,a[k,0]]:=i; 61 end; 62 end; 63 64 var 65 f,f2,vis:array[0..maxn]of longint; 66 xu:array[0..maxm]of longint; 67 time:longint; 68 69 function find(x:longint):longint; 70 begin 71 if vis[x]<>time then 72 begin 73 f[x]:=f2[x]; 74 vis[x]:=time; 75 end; 76 if f[x]=x then exit(x); 77 f[x]:=find(f[x]); 78 exit(f[x]); 79 end; 80 81 function find2(x:longint):longint; 82 begin 83 if f2[x]=x then exit(x); 84 f2[x]:=find2(f2[x]); 85 exit(f2[x]); 86 end; 87 88 function flag(x:longint):boolean; 89 var 90 i:longint; 91 begin 92 i:=0; 93 while x>0 do 94 begin 95 inc(i); 96 if x and 1=1 then 97 begin 98 if find(u[l+i])=find(v[l+i]) then exit(false); 99 if (f[u[l+i]]<>f[v[l+i]])and(find2(u[l+i])=find2(v[l+i])) then exit(false); 100 f[f[u[l+i]]]:=f[v[l+i]]; 101 end; 102 x:=x>>1; 103 end; 104 exit(true); 105 end; 106 107 procedure work; 108 var 109 i,j,s,last:longint; 110 begin 111 ans:=1; 112 for i:=1 to n do 113 f2[i]:=i; 114 for i:=1 to m do 115 begin 116 if w[i]=w[i-1] then xu[i]:=xu[i-1]; 117 if find2(u[i])<>find2(v[i]) then 118 begin 119 inc(xu[i]); 120 f2[f2[u[i]]]:=f2[v[i]]; 121 end; 122 end; 123 for i:=1 to n-1 do 124 if find2(i)<>find2(i+1) then ans:=0; 125 for i:=1 to n do 126 f2[i]:=i; 127 l:=0; 128 last:=0; 129 for i:=1 to m do 130 if w[i]<>w[i+1] then 131 begin 132 s:=0; 133 while last<l do 134 begin 135 inc(last); 136 f2[find2(u[last])]:=find2(v[last]); 137 end; 138 for j:=1 to a[xu[i],0] do 139 begin 140 if a[xu[i],j]>=1<<(i-l) then break; 141 inc(time); 142 if flag(a[xu[i],j]) then inc(s); 143 end; 144 l:=i; 145 ans:=ans*s mod h; 146 end; 147 write(ans); 148 end; 149 150 begin 151 init; 152 work; 153 end.
View Code
转载于:https://www.cnblogs.com/Randolph87/p/3624335.html
1016: [JSOI2008]最小生成树计数 - BZOJ相关推荐
- BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )
不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...
- bzoj 1016: [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 5893 Solved: 2395 [Submit][ ...
- bzoj 1016: [JSOI2008]最小生成树计数【dfs+克鲁斯卡尔】
有一个性质就是组成最小生成树总边权值的若干边权总是相等的 这意味着按边权排序后在权值相同的一段区间内的边能被选入最小生成树的条数是固定的 所以先随便求一个最小生成树,把每段的入选边数记录下来 然后对于 ...
- bzoj 1016 [JSOI2008]最小生成树计数——matrix tree(相同权值的边为阶段缩点)(码力)...
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1016 就是缩点,每次相同权值的边构成的联通块求一下matrix tree.注意gauss里的 ...
- bzoj1016 [JSOI2008]最小生成树计数
1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 6032 Solved: 2452 [Submit][ ...
- BZOJ1016:[JSOI2008]最小生成树计数——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1016 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不 ...
- 【BZOJ1016】【Luogu P4208】 [JSOI2008]最小生成树计数 最小生成树,矩阵树定理
蛮不错的一道题,遗憾就遗憾在数据范围会导致暴力轻松跑过. 最小生成树的两个性质: 不同的最小生成树,相同权值使用的边数一定相同. 不同的最小生成树,将其都去掉同一个权值的所有边,其连通性一致. 这样我 ...
- [JSOI2008]最小生成树计数
OJ题号: BZOJ1016 题目大意: 给定一个无向带权图,求最小生成树的个数. 思路: 先跑一遍最小生成树,统计相同权值的边出现的个数. 易证不同的最小生成树,它们不同的那一部分边的权值实际上是相 ...
- BZOJ1016 [JSOI2008]最小生成树计数
题意:给定一张n<=100,m<=1000的无向图,另外同样权值的边不超过10条,求最小生成树的数目. 思路:首先我们将不同的权值从小到大分开考虑. 我们证明下面定理:一个无向图全部的最小 ...
- P4208 [JSOI2008]最小生成树计数
传送门 首先最小生成树有这么两个性质 1.不同的最小生成树中,每种权值的边出现的个数是确定的2.不同的生成树中,某一种权值的边连接完成后,形成的联通块状态是一样的 打个比方,以下图为例(图是网上的) ...
最新文章
- LaText中插入带上下限的求和符号
- js选择日期即时把两个日期相差天数显示出来?
- (Metro学习三)图片uri保存到本地图片库
- php移动代码,移动专区周级收录如何提交 复制这段php代码即可
- 分享网页设计当中使用进度条打造精美界面最佳例子
- android slidingdrawer 方向,如何使Android SlidingDrawer从左侧滑出?
- python中number函数_Python 数字(Number)
- linux中如何运行html文件路径问题,Linux中如何查询运行文件的全路径的方法
- 三十六、【减小apk包的体积】
- 【MySQL】MySQL常见的读写分离方法
- nagios监控安装及设置案例
- 贴一个数据结构老师布置的作业(各种排序) c 语言实现
- 2017年BackBox5和Ubuntu16.04.1国内更新源
- 重设OS X (macOS)系统帐户密码的几种方法
- 增长黑客手册:如何用数据驱动爆发式增长_思维导图
- mysql 脱裤_mysql 脱裤(脱库)通用脚本 | 学步园
- 新鲜出炉2010笑话集锦,我竟然一个都没听过
- 要么励志故事:要么孤独,要么庸俗
- Matlab的plot函数画线显示空白问题解决
- 中英文说明书丨艾美捷双链RNA定量试剂盒
热门文章
- 如何通俗易懂地让女朋友明白什么是语言模型?
- 融入常识知识的生成式对话摘要
- 她是北大“一个人的毕业照”主人公,2010 级古生物专业独苗,十年后转行搞起了 NLP...
- 【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事!
- nlp基础—11.条件随机场模型(CRF)模型补充
- 灵活地横向扩展:从文件系统到分布式文件系统
- 数据中台公开课丨可以复用的中台架构建设经验与实践
- 神奇的G1——Java全新垃圾回收机制
- 5.7 tensorflow2实现主成分分析(PCA) ——python实战(上篇)
- PyTorch:损失函数loss function