# BZOJ1016: [JSOI2008]最小生成树计数

/**************************************************************
Problem: 1016
User: 96655
Language: C++
Result: Accepted
Time:8 ms
Memory:1516 kb
****************************************************************/

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
int n,m,cnt,tot,ans,sum;
const int maxn=10005;
const int mod=31011;
int fa[maxn/10];
struct Edge
{
int u,v,w;
bool operator<(const Edge &h)const
{
return w<h.w;
}
} e[maxn];
struct data
{
int l,r,c;
} a[maxn];
{
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x;
}
int find(int x)
{
if(x==fa[x])return x;
return find(fa[x]);
}
void dfs(int pos,int now,int k)
{
if(now==a[pos].r+1)
{
if(k==a[pos].c)++sum;
return;
}
int fx=find(e[now].u);
int fy=find(e[now].v);
if(fx!=fy)
{
fa[fx]=fy;
dfs(pos,now+1,k+1);
fa[fx]=fx;
fa[fy]=fy;
}
dfs(pos,now+1,k);
}
int main()
{
for(int i=1; i<=n; i++)
fa[i]=i;
for(int i=1; i<=m; i++)
sort(e+1,e+1+m);
tot=cnt=0;
ans=1;
for(int i=1; i<=m; i++)
{
if(e[i].w!=e[i-1].w)
{
a[++cnt].l=i;
a[cnt-1].r=i-1;
}
int fx=find(e[i].u);
int fy=find(e[i].v);
if(fx!=fy)
{
fa[fx]=fy;
a[cnt].c++;
tot++;
}
}
a[cnt].r=m;
if(tot!=n-1)
{
printf("0\n");
return 0;
}
for(int i=1; i<=n; i++)
fa[i]=i;
for(int i=1; i<=cnt; i++)
{
sum=0;
dfs(i,a[i].l,0);
ans=(ans*sum)%mod;
for(int j=a[i].l; j<=a[i].r; j++)
{
int fx=find(e[j].u);
int fy=find(e[j].v);
if(fx!=fy)fa[fx]=fy;
}
}
printf("%d\n",ans);
return 0;
}
View Code

posted @ 2015-11-06 21:18  shuguangzw  阅读(160)  评论(0编辑  收藏