题意:
给一个图,问其最小生成树是否唯一。
题解:
用Kruskal 算出最小生成树的值,并记录每一条边,然后枚举去掉这些边 看其是否也能构成最小生成树且值相同。
注意 在删边后,可能图构不成一棵树,得判断一下。
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<vector> #include<map> using namespace std; typedef long long ll; const int maxn = 10005; int f[maxn]; int n,cnt,m; int vis[maxn]; struct node { int u,v; int w; bool operator < (const node &a)const { return w<a.w; } } edge[maxn]; int Find(int x) { return x==f[x]?x:f[x]=Find(f[x]); } void add(int u,int v,int w) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt++].w=w; } void kruskal() { int ans=0; int cntt=0; int flag=1; for(int i=0; i<=n; i++)f[i]=i; sort(edge,edge+cnt); for(int i=0; i<cnt; i++) { int x=edge[i].u; int y=edge[i].v; int fx=Find(x); int fy=Find(y); if(fx!=fy) { f[fx]=fy; vis[cntt++]=i; ans+=edge[i].w; } } for(int i=0;i<cntt;i++) { for(int k=0; k<=n; k++)f[k]=k; int sum=0,res=0; for(int j=0;j<cnt;j++) { if(j==vis[i])continue; int x=edge[j].u; int y=edge[j].v; int fx=Find(x); int fy=Find(y); if(fx!=fy) { f[fx]=fy; res+=edge[j].w; sum++; } } if(ans==res && sum==n-1){flag=0;break;}///判断是否能构成树 且 是否与最小生成树相等 } if(flag)printf("%d\n",ans); else printf("Not Unique!\n"); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); cnt=0; for(int i=1; i<=m; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); } kruskal(); } return 0; }
kruskal
原文地址:https://www.cnblogs.com/j666/p/11617275.html
时间: 2024-10-19 17:41:16