标签:去掉 ios bzoj nbsp lan ref oid 矩阵 return
想我这样的zz根本不会矩阵树。。。。。
题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=1016
首先,如果用上所有边都做不出最小生成树,答案显然是0。。
然后,对于一个图的所有最小生成树,他们有的权值为w的边数一定是一样多的。。
所以先求出一个最小生成树,然后把其中一条边去掉,再搜索一下在相同权值的边中是否仍然可以保持连通性。
根据乘法原理求出答案。。。
然后就没有然后了。。。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define M 1010
#define mod 31011
using namespace std;
int n,m,cnt,tot;
int f[M],w[M],sum[M];
bool c[M];
struct edge{
int l,r,w;
}e[M],a[M];
bool cmp(edge p,edge q){return p.w<q.w;}
int find(int x){
if(f[x]==x) return f[x];
return find(f[x]);
}
void RE(){for(int i=1;i<=n;i++) f[i]=i;}
void dfs(int x,int now,int k){
if(now==a[x].r+1){
if(k==a[x].w)tot++;
return;
}
int xx=find(e[now].l),yy=find(e[now].r);
if(xx!=yy){
f[xx]=yy;
dfs(x,now+1,k+1);
f[xx]=xx;f[yy]=yy;
}
dfs(x,now+1,k);
}
int main(){
int ans=1;
cnt=0;tot=0;
int xx,yy;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].w);
sort(e+1,e+1+m,cmp);
RE();
for(int i=1;i<=m;i++){
if(e[i].w!=e[i-1].w){a[cnt].r=i-1;cnt++;a[cnt].l=i;}
xx=find(e[i].l);yy=find(e[i].r);
if(xx!=yy){f[xx]=yy;a[cnt].w++;tot++;}
}
a[cnt].r=m;
if(tot+1!=n){printf("0\n");return 0;}
RE();
for(int i=1;i<=cnt;i++){
tot=0;
dfs(i,a[i].l,0);
ans=(ans*tot)%mod;
for(int j=a[i].l;j<=a[i].r;j++){
xx=find(e[j].l);yy=find(e[j].r);
if(xx!=yy) f[xx]=yy;
}
}
printf("%d\n",ans);
return 0;
}
This passage is made by Iscream-2001.
BZOJ 1016--最小生成树计数(深搜&kruskal)
标签:去掉 ios bzoj nbsp lan ref oid 矩阵 return
原文地址:http://www.cnblogs.com/Yuigahama/p/7724057.html