Description
Input
Output
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!
题意:判断最小生成树是否唯一
思路:首先求出最小生成树,记录现在这个最小生成树上所有的边,然后通过取消其中一条边,找到这两点上其他的边形成一棵新的生成树,求其权值,通过枚举所有可能,通过这些权值看与原最小生成树的权值比较看其是否唯一
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; struct node { int x,y,dis; int flag; } a[10005]; int cmp(node x,node y) { return x.dis<y.dis; } int father[105],n; int kruskal(int num,int m) { int i,j,k; int ans = 0,cnt = 1; for(i = 0; i<m; i++) { if(i == num)//除去这条边之后再求一次最小生成树 continue; int s1 = father[a[i].x]; int s2 = father[a[i].y]; if(s1!=s2) { ans+=a[i].dis; cnt++; father[s2] = s1; for(j = 0; j<=n; j++) if(father[j] == s2) father[j] = s1; } } if(cnt!=n) return -1; else return ans; } int main() { int m,i,j,t,sum,ans,cnt; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i = 0; i<=n; i++) father[i] = i; for(i = 0; i<m; i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].dis); a[i].flag = 0; } sort(a,a+m,cmp); cnt = 1; ans = 0; for(i = 0; i<m; i++) { int s1 = father[a[i].x]; int s2 = father[a[i].y]; if(s1!=s2) { a[i].flag = 1; ans+=a[i].dis; cnt++; father[s2] = s1; for(j = 0; j<=n; j++) if(father[j] == s2) father[j] = s1; } } int flag = 0; for(i = 0; i<m; i++)//枚举所有原最小生成树上的边 { if(a[i].flag==0) continue; sum = 0; for(j = 0; j<=n; j++)//初始化 father[j] = j; sum = kruskal(i,m); if(sum == ans)//与之前的最小生成树比较,如果相等,那么肯定不是唯一的 { flag = 1; break; } } if(flag) printf("Not Unique!\n"); else printf("%d\n",ans); } return 0; }