您的位置:首页 > Web前端 > JavaScript

【kruscal】【最小生成树】【搜索】bzoj1016 [JSOI2008]最小生成树计数

2014-10-11 15:33 246 查看
不用Matrix-tree定理什么的,一边kruscal一边 对权值相同的边 暴搜即可。将所有方案乘起来。

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
struct Disjoint_Set
{
int fa[101],rank[101];
void init(){for(int i=1;i<=n;i++) fa[i]=i;}
int findroot(int x)
{
if(fa[x]==x) return x;
int rt=findroot(fa[x]);
fa[x]=rt;
return rt;
}
void Union(int U,int V)
{
if(rank[U]<rank[V]) fa[U]=V;
else
{
fa[V]=U;
if(rank[U]==rank[V]) rank[U]++;
}
}
};
Disjoint_Set S,used;
struct Edge{int u,v,w;};
bool cmp(const Edge &a,const Edge &b){return a.w<b.w;}
Edge edges[1001];
int res,ans=1,tot,cnt,sta,end;
void dfs(int cur,int sum,Disjoint_Set now)
{
if(cur>end)
{
if(sum==cnt) res++;
return;
}
dfs(cur+1,sum,now);
int f1=now.findroot(edges[cur].u),f2=now.findroot(edges[cur].v);
if(f1!=f2) {now.Union(f1,f2); dfs(cur+1,sum+1,now);}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].w);
sort(edges+1,edges+m+1,cmp);
S.init();used.init();
for(int i=1;i<=m;i++)
{
if(edges[i].w!=edges[i-1].w) {used=S; cnt=0; sta=i;}
int f1=S.findroot(edges[i].u),f2=S.findroot(edges[i].v);
if(f1!=f2) {S.Union(f1,f2); tot++; cnt++;}
if(edges[i].w!=edges[i+1].w)
{
res=0; end=i;
dfs(sta,0,used);
ans=((ans%31011)*(res%31011))%31011;
}
else if(tot==n-1)
{
res=0;
for(int j=i+1;j<=m;j++)
if(edges[j].w!=edges[i].w)
{
end=j-1;
goto OUT;
}
end=m;
OUT:dfs(sta,0,used);
ans=((ans%31011)*(res%31011))%31011;
break;
}
}
printf("%d\n",tot==n-1 ? ans : 0);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: