想看更多的解题报告: http://iyenn.com/rec/1824570.html
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:给出n个点,m条边,每条边有相应的权值,问这个图的最小生成树是否唯一
解题思路:先求出原图的最小生成树,标记哪些边是这个最小生成树的边,然后去掉其中的一条边求图的最小生成树,看和原图的最小生成树是否相等,如果有一个相等,那么输出Not Unique!,如果都不想等,那么输出最小生成树就可以了
- /*
- Memory 248K
- Time 16MS
- */
- #include
- using namespace std;
- #define MAXV 110
- #define MAXE 10100
-
- typedef struct{
- int s,t,w,flag;
- }Edge;
-
- Edge edge[MAXE];
- int n,m;
- int set[MAXV];
-
- int cmp(const void *a,const void *b){
- return ((Edge *)a)-((Edge *)b);
- }
-
- int find(int x){
- int rt;
- if(set[x]!=x){
- rt=find(set[x]);
- set[x]=rt;
- return set[x];
- }else return x;
- }
-
- bool Union(int a,int b){
- int fa,fb;
- fa=find(a);
- fb=find(b);
- if(fa==fb) return 0;
- set[fa]=fb;
- return 1;
- }
-
- int kruskal(){
- int i,num=0,cnt=0;
- for(i=0;i<=n;i++) set[i]=i;
-
- for(i=0;i
- if(Union(edge[i].s,edge[i].t)){
- num+=edge[i].w;
- edge[i].flag=1; //标记这条边是最小生成树的边
- if(++cnt==(n-1)) break;
- }
- }
- if(cnt==n-1) return num;
- return -1; //如果没有最小生成树
- }
-
- int kruskalt(){
- int i,num=0,cnt=0;
- for(i=0;i<=n;i++) set[i]=i;
-
- for(i=0;i
- if(Union(edge[i].s,edge[i].t)){
- num+=edge[i].w;
- if(++cnt==(n-1)) break;
- }
- }
- if(cnt==n-1) return num;
- return -1;
- }
-
- int main(){
- int i,s,ans,tmp;
- int Case;
- scanf("%d",&Case);
- while(Case--){
- scanf("%d%d",&n,&m);
- for(i=0;i
- scanf("%d%d%d",&edge[i].s,&edge[i].t,&edge[i].w);
- edge[i].flag=0;
- }
- qsort(edge,m,sizeof(edge[0]),cmp);
- ans=kruskal();
-
- for(i=0;i
- if(edge[i].flag){ //判断去除i边的图的最小生成树是否与前面最小生成树相等
- s=edge[i].s;
- edge[i].s=edge[i].t; //两个顶点相等不会加入最小生成树里面了
- tmp=kruskalt();
- if(tmp!=-1 && ans==tmp) break;
- edge[i].s=s; //记得还原
- }
- }
- if(i==m) printf("%d\n",ans);
- else printf("Not Unique!\n");
- }
- return 0;
- }
注:本文转载自blog.csdn.net的wangjian8006的文章"http://blog.csdn.net/wangjian8006/article/details/7977705"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
评论记录:
回复评论: