POJ-1679 The Unique MST (判断最小生成树的唯一性)
<题目链接>
题目大意:
给定一张无向图,判断其最小生成树是否唯一。
解题分析:
对图中每条边,扫描其它边,如果存在相同权值的边,则标记该边;用kruskal求出MST。
如果MST中无标记的边,则该MST唯一;否则,在MST中依次去掉标记的边,再求MST,若求得MST权值和原来的MST 权值相同,则MST不唯一。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int M = 1e4+100; struct EDGE{ int u,v,w; int eq,used,del; }edge[M]; int n,m; int father[M]; bool flag; bool cmp(EDGE a,EDGE b){ return a.w<b.w; } int find(int x){ if(father[x]!=x)father[x]=find(father[x]); return father[x]; } int Kruscal(){ for(int i=0;i<1e4+10;i++)father[i]=i; int sum=0,num=0; for(int i=0;i<m;i++){ if(edge[i].del)continue;//如果该边被删除,则跳过 int u=edge[i].u,v=edge[i].v,w=edge[i].w; if(find(u)!=find(v)){ sum+=w,num++; if(flag)edge[i].used=1;//将第一次最小生成树的所有边标记 father[find(v)]=find(u); } if(num>=n-1)break; } return sum; } int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); memset(edge,0,sizeof(edge)); //用memset能给edge内的所有变量初始化吗? for(int i=0;i<m;i++){ scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); } for(int i=0;i<m;i++){ for(int j=0;j<m;j++){ if(i==j)continue; if(edge[i].w==edge[j].w)edge[i].eq=1;//判断是否有和它权值相同的边 } } sort(edge,edge+m,cmp); flag=true; int cnt=Kruscal(); flag=false; bool fp=false; for(int i=0;i<m;i++){ if(edge[i].eq&&edge[i].used){ edge[i].del=1;//如果这条边在第一次求的最小生成树中,并且还有与这条边权值相同的边,那么就试着删除这条边,再跑一遍最小生成树,看得到的权值总和是否与第一次的最小生成树相同 int res=Kruscal(); if(res==cnt){ fp=true; printf("Not Unique!\n"); break; } edge[i].del=0; } } if(!fp)printf("%d\n",cnt); } return 0; }
2018-10-01
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。