标签:poj
题意:判断最小生成树是否唯一,
若唯一,输出最小权值和,否则,输出 Not Unique!
判断最小生成树是否唯一的思路:
1、对图中的每一条边,扫描其他边,如果存在相同权值的边,则对该边做标记
2、然后用Kruskal算法或Prim算法求MST
3、求得MST后,如果该MST中未包含做了标记的边,即可判断MST唯一;
如果包含做了标记的边,则依次去掉这些边的一条边,再求MST,
如果求得的MST权值和原来的MST的权值一样,即可判断MST不唯一。
个人思路是先求最小生成树,并标记最小生成树包含的边,
再依次判断是否有相同权值的边,若存在,将最小生成树的该条边去掉,
重新求最小生成树,若得到的权值与原来的最小权值和相等,则不唯一
#include<stdio.h> #include<algorithm> #include<string.h> #define INF 999999 using namespace std; int n,m,k,f[105],path[105]; struct stu { int u,v,w; }edge[10010]; int cmp(stu a,stu b) { return a.w<b.w; } int find(int x) { if(x!=f[x]) f[x]=find(f[x]); return f[x]; } int kruskal(int flag) { int i,x,y,sum=0; for(i=1;i<=n;i++) f[i]=i; k=0; for(i=1;i<=m;i++){ if(edge[i].w==INF) continue; x=find(edge[i].u); y=find(edge[i].v); if(x!=y){ sum+=edge[i].w; if(flag) path[k]=i; //第一次求最小生成树时记录路径 k++; if(k==n-1) break; f[x]=y; } } if(k!=n-1) sum=-1; return sum; } int main() { int T,i,j,ans,s,t,flag,num; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); memset(edge,0,sizeof(edge)); for(i=1;i<=m;i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); sort(edge+1,edge+m+1,cmp); ans=kruskal(1); flag=1; num=k; for(i=0;i<num&&flag;i++){ j=path[i]; //依次判断是否存在与路径相同权值的边 if(edge[j-1].w==edge[j].w||edge[j+1].w==edge[j].w){ t=edge[j].w; edge[j].w=INF; //若存在,将其标记为极大值,表示去掉此边,再求最小生成树 s=kruskal(0); if(s==ans) flag=0; edge[j].w=t; //将该边还原为原值 } } if(!flag) printf("Not Unique!\n"); else printf("%d\n",ans); } return 0; }
poj 1679 The Unique MST (判断最小生成树是否唯一)
标签:poj
原文地址:http://blog.csdn.net/acm_code/article/details/41211537