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

1016: [JSOI2008]最小生成树计数

2017-02-22 20:24 513 查看
传送门

并查集好题。

用暴力求出最小生成树,确定每一种长度的边在图中的数量。

又Kruscal算法流程知,每一种长度的边在图中的数量一定(否则存在更优解)

对于每一个长度的边,爆搜求出方案个数。

运用乘法原理求解即可。

P.S:本题并查集无需路径压缩。/**************************************************************
Problem: 1016
User: zhouyuyang
Language: C++
Result: Accepted
Time:8 ms
Memory:2620 kb
****************************************************************/

#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
struct orzhhd{
int x,y,z;
}a[10005],e[100005];
int n,m,u,v,ans,sum,cnt,tot;
int fa[10005];
bool cmp(orzhhd a,orzhhd b){
return a.z<b.z;
}
int getf(int x){
return fa[x]==x?x:getf(fa[x]);
}
void dfs(int x,int now,int k){
if (now==e[x].y+1){
if (k==e[x].z) sum++;
return;
}
int u=getf(a[now].x);
int v=getf(a[now].y);
if (u!=v){
fa[u]=v;
dfs(x,now+1,k+1);
fa[u]=u;
fa[v]=v;
}
dfs(x,now+1,k);
return;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
sort(a+1,a+m+1,cmp);
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++){
u=getf(a[i].x);
v=getf(a[i].y);
if (a[i].z!=a[i-1].z){
e[cnt].y=i-1;
cnt++;
e[cnt].x=i;
}
if (u!=v){
fa[u]=v;
e[cnt].z++;
tot++;
}
}
e[cnt].y=m;
for (int i=1;i<=n;i++) fa[i]=i;
if (tot!=n-1){
printf("0");
return 0;
}
ans=1;
for (int i=1;i<=cnt;i++){
sum=0;
dfs(i,e[i].x,0);
ans=(ans*sum)%31011;
for (int j=e[i].x;j<=e[i].y;j++){
u=getf(a[j].x);
v=getf(a[j].y);
if (u!=v) fa[u]=v;
}
}
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: