次小生成树

我们大部分都对最小生成树了解的多一些,一般求最小生成树的算法是prim、kurskal,那么对于次小生成树,我们也可以用上面两种算法来求解

算法解释
这两种算法的思路都是相同的,首先求出最小生成树,我们枚举每条不在最小生成树上的边,并把这条边放到最小生成树上面,然后就一定会形成环,那么我们在这条环路中取出一条最长的路(除了新加入的那一条边)。最终我们得到的权值就是次小生成树的权值。

这里我采用的是kruscal求次小生成树

不妨开一个二维数组maxd[u][v] 代表从 u 到 v的最小距离,因为kruscal求最小生成树的时候就是从最短的距离开始枚举的嘛,所以一开始枚举的肯定是最小的!

之后我们如何去求次小生成树呢?

首先假设ans代表最小生成树的值,并且我们把这个最小生成树的所有边都标记。然后我们去枚举未被标记的边(从小开始枚举),找到一个就进行替换  

 1 cisum = std::min(cisum,ans+e[i].w-maxd[e[i].u][e[i].v]); 

 

板子题:The Unique MST

 

题目连接:https://vjudge.net/problem/POJ-1679

 

直接上板子吧

  1 #include <math.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <string>
  7 #include <string.h>
  8 #include <vector>
  9 #include <map>
 10 #include <stack>
 11 #include <set>
 12 #include <queue>
 13 
 14 
 15 #define LL long long
 16 #define INF 0x3f3f3f3f
 17 #define ls nod<<1
 18 #define rs (nod<<1)+1
 19 const int maxn = 2e4+10;
 20 const double eps = 1e-9;
 21 std::vector<int> G[110];
 22 int maxd[110][110];
 23 
 24 int n,m,ans,cnt,cisum,fa[5050];
 25 
 26 struct node{
 27     int u, v, w;
 28     bool vis;
 29 }e[maxn];
 30 
 31 bool cmp(node a, node b)
 32 {
 33     return a.w < b.w;
 34 }
 35 
 36 int fid(int x)
 37 {
 38     return x == fa[x] ? x : fid(fa[x]);
 39 }
 40 
 41 void init(int n)
 42 {
 43     for(int i = 1; i <= n; i++) {
 44         G[i].clear();
 45         G[i].push_back(i);
 46         fa[i] = i;
 47     }
 48     ans = 0;
 49     cnt = 0;
 50 }
 51 
 52 void kruskal()
 53 {
 54     std::sort(e+1, e+m+1, cmp);
 55     for(int i = 1; i <= m; i++) {
 56         int eu = fid(e[i].u);
 57         int ev = fid(e[i].v);
 58         if(eu == ev) {
 59             continue;
 60         }
 61         ans += e[i].w;
 62         e[i].vis = true;
 63         int len_eu = G[eu].size();
 64         int len_ev = G[ev].size();
 65         for (int j=0;j<len_eu;j++) {
 66             for (int k=0;k<len_ev;k++) {
 67                 maxd[G[eu][j]][G[ev][k]] = maxd[G[ev][k]][G[eu][j]] = e[i].w;
 68             }
 69         }
 70         fa[ev] = eu;
 71         for (int j=0;j<len_ev;j++) {
 72             G[eu].push_back(G[ev][j]);
 73         }
 74         if(++cnt == n-1) {
 75             break;
 76         }
 77     }
 78     cisum = INF;
 79     for (int i=1;i<=m;i++) {
 80         if (!e[i].vis) {
 81             cisum = std::min(cisum,ans+e[i].w-maxd[e[i].u][e[i].v]);
 82         }
 83     }
 84 }
 85 
 86 int main() {
 87     int T;
 88     scanf("%d",&T);
 89     while (T--) {
 90         scanf("%d%d",&n,&m);
 91         for (int i=1;i<=m;i++) {
 92             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
 93             e[i].vis = false;
 94         }
 95         init(n);
 96         kruskal();
 97         if (cisum>ans)
 98             printf("%d\n",ans);
 99         else
100             printf("Not Unique!\n");
101     }
102     return 0;
103 }

 

posted @ 2019-11-19 22:35  _Ackerman  阅读(226)  评论(0编辑  收藏  举报