【最小生成树】BZOJ1016: [JSOI2008]最小生成树计数
2015-06-10 09:59
696 查看
Description
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。Solution
把所有边权相同的视为边组,每一组边组在最小生成树的条数是固定的,对连通性的贡献也是固定的。(证明可以看http://www.cnblogs.com/Fatedayt/archive/2012/05/10/2494877.html)在确定贡献之后,爆搜每一组边即可。
用矩阵树也可以做,然而我还不会QwQ。
Code
并查集不能路径压缩,不然就不好回溯时还原了。#include<cstdio> #include<algorithm> using namespace std; const int maxn=1e3+5,mod=31011; struct edge{ int u,v,w; bool operator<(const edge&a) const{return w<a.w;} }e[maxn]; int l[maxn],r[maxn],t[maxn],cnt; int p[maxn]; int find(int x){return p[x]==x?x:find(p[x]);} int n,m; int ret; void dfs(int i,int j,int k){ if(j==r[i]+1){ if(k==t[i]) ret++,ret%=mod; return; } int x=find(e[j].u),y=find(e[j].v); if(x!=y){ p[x]=y; dfs(i,j+1,k+1); p[x]=x; } dfs(i,j+1,k); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); sort(e+1,e+m+1); int tot=0; for(int i=1;i<=n;i++) p[i]=i; for(int i=1;i<=m;i++){ if(i==1||e[i].w!=e[i-1].w){ r[cnt]=i-1; l[++cnt]=i; } int x=find(e[i].u),y=find(e[i].v); if(x!=y){ t[cnt]++; tot++; p[x]=y; } } r[cnt]=m; if(tot!=n-1){ printf("0\n"); return 0; } for(int i=1;i<=n;i++) p[i]=i; int ans=1; for(int i=1;i<=cnt;i++){ ret=0; dfs(i,l[i],0); ans=ans*ret,ans%=mod; for(int j=l[i];j<=r[i];j++){ int x=find(e[j].u),y=find(e[j].v); if(x!=y) p[x]=y; } } printf("%d",ans); return 0; }
相关文章推荐
- js身份证验证
- JavaScript中计算网页中某个元素的位置
- 代理解决js跨域
- JavaScript去掉字符串前后空格
- javascript提示抖动实现方法
- JS 函数访问方式总结
- JSON 4000 学习
- json数据解析
- 详解JavaScript中getFullYear()方法的使用
- JavaScript中判断函数、变量是否存在
- JavaScript检查手机格式是否错误
- Javascript中实现String.startsWith和endsWith方法
- D3js-画二维坐标轴(x轴,y轴)
- Javascript中判断对象是否为空
- javascript 清空iframe 支持IE
- JavaScript判断E-mail地址是否合法
- javascript事件委托的方式绑定详解
- JavaScript 自定义对象
- Javascript:谈谈JS的全局变量跟局部变量(转zyz511919766)
- 浅析JavaScript动画