1016: [JSOI2008]最小生成树计数
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6643 Solved: 2711
[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,0
00。数据保证不会出现自回边和重边。注意:具有相同权值的边不会超过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
根据kruskal算法的基础是贪心,我们可以得出,不同的最小生成树的边权序列是一样的
我们先做出kruskal得出最终的边权序列,然后逐个枚举每个边权有多少种不同的组成方法
最后乘法原理乘起来即可,要注意使用并查集的时候不要带路径压缩,不要的话dfs就回溯不了了,但这样效率会变低
不嫌麻烦的话写两个,我太懒了QAQ
1 #include <bits/stdc++.h> 2 #define ll long long 3 #define inf 1000000 4 #define eps 1e-7 5 #define MOD 31011 6 using namespace std; 7 inline int read(){ 8 int x=0;int f=1;char ch=getchar(); 9 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} 10 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} 11 return x*f; 12 } 13 const int MAXN=1e6+10; 14 struct node{ 15 int x,y,v; 16 }e[MAXN]; 17 struct edge{ 18 int l,r,v; 19 }a[MAXN]; 20 int f[MAXN],cnt,tot,sum; 21 inline int find(int x){ 22 return x==f[x]?x:find(f[x]); 23 } 24 inline bool mycmp(node n,node m){ 25 return n.v<m.v; 26 } 27 inline void dfs(int st,int now,int k){ 28 if(now==a[st].r+1){ 29 if(k==a[st].v) sum++; 30 return; 31 } 32 int fx=find(e[now].x);int fy=find(e[now].y); 33 if(fx!=fy){ 34 f[fx]=fy; 35 dfs(st,now+1,k+1); 36 f[fx]=fx;f[fy]=fy; 37 } 38 dfs(st,now+1,k); 39 } 40 int main(){ 41 int n=read();int m=read(); 42 for(int i=1;i<=m;i++){ 43 e[i].x=read();e[i].y=read();e[i].v=read(); 44 } 45 for(int i=1;i<=n;i++) f[i]=i; 46 sort(e+1,e+m+1,mycmp); 47 for(int i=1;i<=m;i++){ 48 if(e[i].v!=e[i-1].v){ 49 a[++cnt].l=i;a[cnt-1].r=i-1; 50 } 51 int fx=find(e[i].x);int fy=find(e[i].y); 52 if(fx!=fy){ 53 a[cnt].v++;f[fx]=fy;tot++; 54 } 55 } 56 a[cnt].r=m; 57 for(int i=1;i<=n;i++) f[i]=i; 58 if(tot!=n-1){ 59 cout<<0<<endl;return 0; 60 } 61 int ans=1; 62 for(int i=1;i<=cnt;i++){ 63 sum=0; 64 dfs(i,a[i].l,0); 65 ans*=sum; 66 ans%=MOD; 67 for(int j=a[i].l;j<=a[i].r;j++){ 68 f[find(e[j].x)]=find(e[j].y); 69 } 70 } 71 cout<<ans<<endl; 72 return 0; 73 }