标签:
次小生成树:所谓的次小生成树,是指在边集与某一最小生成树的边集不完全相同的其它生成树中值最小的那个。因此在数值上,最小生成树可能会等于次小生成树,这种情况也可以看做最小生成数。
思路:最直观的解法是,首先求出最小生成树,并且记录最小生成树中的边,然后再枚举删除最小生成树的边并同时求最小生成树。
以POJ1679为例,Kruskal求次小生成树代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define _Clr(x, y) memset(x, y, sizeof(x)) 5 #define INF 0x3f3f3f3f 6 #define N 110 7 using namespace std; 8 9 struct Edge 10 { 11 int a, b; 12 int c; 13 bool operator < (const Edge &a) const 14 { 15 return c < a.c; 16 } 17 }edge[N*N]; 18 int bleg[N], n, m; 19 int mst_edge[N]; 20 21 int find(int x) 22 { 23 int y = x; 24 while(y != bleg[y]) 25 y = bleg[y]; 26 while(x != bleg[x]) 27 { 28 int px = bleg[x]; 29 bleg[x] = y; 30 x = px; 31 } 32 return y; 33 } 34 35 void Union(int a, int b) 36 { 37 int pa=find(a), pb=find(b); 38 if(pa != pb) 39 bleg[pa] = pb; 40 } 41 42 inline void Init() 43 { 44 for(int i=0; i<=n; i++) 45 bleg[i] = i; 46 } 47 48 void Kruskal() 49 { 50 int mst_1=0; 51 Init(); 52 _Clr(mst_edge, 0); 53 sort(edge, edge+m); 54 int k=0; 55 for(int i=0; i<m && k<n-1; i++) 56 { 57 int a=find(edge[i].a); 58 int b=find(edge[i].b); 59 if(a != b) 60 { 61 mst_edge[k] = i; 62 Union(a, b); 63 mst_1 += edge[i].c; 64 k++; 65 } 66 } 67 // 枚举删除最小生成树中所有边求MST 68 for(int i=0; i<n-1; i++) 69 { 70 int mst_2=0, k=0; 71 Init(); 72 for(int j=0; j<m && k<n-1; j++) 73 { 74 if(mst_edge[i] == j) continue; 75 int a=find(edge[j].a); 76 int b=find(edge[j].b); 77 if(a != b) 78 { 79 Union(a, b); 80 mst_2 += edge[j].c; 81 k++; 82 } 83 } 84 if(mst_1==mst_2 && k==n-1) 85 { 86 puts("Not Unique!"); 87 return; 88 } 89 } 90 printf("%d\n", mst_1); 91 } 92 93 int main() 94 { 95 int T; 96 scanf("%d", &T); 97 while(T--) 98 { 99 scanf("%d%d", &n, &m); 100 for(int i=0; i<m; i++) 101 scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].c); 102 Kruskal(); 103 } 104 return 0; 105 }
标签:
原文地址:http://www.cnblogs.com/khan724/p/4433681.html