BZOJ 1016: [JSOI2008]最小生成树计数
最小生成树计数:
最小生成树的两个性质:
1.不同的最小生成树中,每种边出现的个数是确定的
2.不同的生成树中,某一种边连接完成后,形成的联通块状态是一样的
1016: [JSOI2008]最小生成树计数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3394 Solved: 1341
[Submit][Status][Discuss]
Description
现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树。(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的)。由于不同的最小生成树可能很多,所以你只需要输出方案数对31011的模就可以了。
Input
第一行包含两个数,n和m,其中1<=n<=100; 1<=m<=1000; 表示该无向图的节点数和边数。每个节点用1~n的整数编号。接下来的m行,每行包含两个整数:a, b, c,表示节点a, b之间的边的权值为c,其中1<=c<=1,000,000,000。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过10条。
Output
输出不同的最小生成树有多少个。你只需要输出数量对31011的模就可以了。
Sample Input
1 2 1
1 3 1
1 4 1
2 3 2
2 4 1
3 4 1
Sample Output
HINT
Source
/* *********************************************** Author :CKboss Created Time :2015年05月17日 星期日 09时44分48秒 File Name :BZOJ1016.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <cmath> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> using namespace std; typedef long long int LL; const LL maxn=1100; const LL mod=31011; LL n,m; struct Edge { LL u,v,len; }edge[maxn]; bool cmp(Edge a,Edge b) { return a.len<b.len; } LL q; LL a[maxn]; LL num[maxn]; LL fa[110]; void init() { for(LL i=0;i<110;i++) fa[i]=i; } LL find(LL u) { if(u==fa[u]) return u; return fa[u]=find(fa[u]); } void kruskal() { for(LL i=0;i<m;i++) { LL u=find(edge[i].u); LL v=find(edge[i].v); LL len=edge[i].len; if(u==v) continue; else { fa[u]=v; if(a[q]!=len) a[++q]=len; num[q]++; } } } LL find2(LL x) { if(x==fa[x]) return x; return find2(fa[x]); } LL part[maxn]; void dfs(LL id,LL from,LL to,LL num) { if(num==0) { part[id]++; if(part[id]>=mod) part[id]-=mod; return ; } for(LL i=from;i<=to;i++) { LL u=find2(edge[i].u); LL v=find2(edge[i].v); if(u==v) continue; else { LL t=fa[u]; fa[u]=v; dfs(id,i+1,to,num-1); fa[u]=t; } } } bool flag; void Link(LL id,LL from,LL to,LL num) { if(flag) return ; if(num==0) { flag=true; return ; } for(LL i=from;i<=to&&flag==false;i++) { LL u=find2(edge[i].u); LL v=find2(edge[i].v); if(u==v) continue; else { LL t=fa[u]; fa[u]=v; Link(id,i+1,to,num-1); if(flag) return ; fa[u]=t; } } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); init(); scanf("%lld%lld",&n,&m); for(LL i=0,u,v,w;i<m;i++) { scanf("%lld%lld%lld",&u,&v,&w); edge[i]=(Edge){u,v,w}; } sort(edge,edge+m,cmp); kruskal(); int go=find(1); for(int i=2;i<=n;i++) { if(go==find(i)) continue; else { go=-1; break; } } if(go==-1) { puts("0"); return 0; } init(); LL from=0,to=0; for(LL i=1;i<=q;i++) { for(LL j=from;j<m;j++) if(edge[j].len==a[i]) to=j; dfs(i,from,to,num[i]); flag=false; Link(i,from,to,num[i]); from=to+1; } LL ans=part[1]%mod; for(LL i=2;i<=q;i++) { ans*=part[i]; ans%=mod; } printf("%lld\n",ans%mod); return 0; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。