再补个water……
题目大意:给一个图,问其中的最小生成树是否唯一。
思路:用kruscal稍微变形,在生成过程中,找到一条边E1的两个点在两个不同的集合中,
则向后寻找跟此边权值相同的所有边,如果有一条边E2的两个点跟E1的两个点在相同的集合中,则此图最小生成树不唯一。
因为这两条边都可以选择。
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 #define VEX_NUM 110 6 #define EDGE_NUM 22000 7 8 struct path 9 { 10 int u,v,cost; 11 }p[EDGE_NUM]; 12 int UF[VEX_NUM]; 13 int get_root(int n) 14 { 15 return UF[n] == n? n: UF[n] = get_root(UF[n]); 16 } 17 int cmp(constvoid* a, constvoid* b) 18 { 19 return (*(path *)a).cost - (*(path *)b).cost; 20 } 21 bool check(int tmpu, int tmpv, int rootu, int rootv) 22 { 23 if(tmpu == rootu && tmpv == rootv) returntrue; 24 if(tmpu == rootv && tmpv == rootu) returntrue; 25 returnfalse; 26 } 27 int kruscal(int vexnum, int pathnum) 28 { 29 int i,j,rootu,rootv,tmpu,tmpv,dis,ret; 30 ret =0; 31 for(i =1; i <= vexnum; i++) 32 UF[i] = i; 33 for(i =0; i < pathnum; i++) 34 { 35 rootu = get_root(p[i].u); 36 rootv = get_root(p[i].v); 37 dis = p[i].cost; 38 if(rootu != rootv) 39 { 40 for(j = i+1; j < pathnum; j++) 41 { 42 if(p[j].cost != dis)break; 43 tmpu = get_root(p[j].u); 44 tmpv = get_root(p[j].v); 45 if(check(tmpu,tmpv,rootu,rootv)) return-1; 46 } 47 UF[rootu] = rootv; 48 ret += p[i].cost; 49 } 50 } 51 return ret; 52 } 53 int main() 54 { 55 int i,t,n,m,a,b,c,r; 56 scanf("%d",&t); 57 while(t--) 58 { 59 scanf("%d%d",&n,&m); 60 for(i =0; i < m; i++) 61 { 62 scanf("%d%d%d",&a,&b,&c); 63 p[i].u = a; 64 p[i].v = b; 65 p[i].cost = c; 66 } 67 qsort(p, m, sizeof(path), cmp); 68 r = kruscal(n,m); 69 if(r ==-1) printf("Not Unique!\n"); 70 else printf("%d\n",r); 71 } 72 return0; 73 }