次小生成树的两种写法(重边or不重边)

// 如果不重边 可用prim算法 在最普通prim基础上添加used[][] 和 path[][] 数组,used[i][j]表示i到j这条无向边是否添加在(第一次求得的)最小生成树中, path[i][j]表示i到j(可理解为这条树链)中边的最大值。

次小树 可理解为i--j这条边没有用到,现在选取它作为生成树的一条边,这样i->j就形成一个环,所以需要删除原本i->j上最长的边,这样才可能是次小树,因此枚举i,j 计算MST

UVA 10600

  1 /*
  2  * @Promlem: 
  3  * @Time Limit: ms
  4  * @Memory Limit: k
  5  * @Author: pupil-XJ
  6  * @Date: 2019-10-21 22:54:50
  7  * @LastEditTime: 2019-10-21 23:32:16
  8  */
  9 #include<cstdio>
 10 #include<cstring>
 11 #include<cmath>
 12 #include<iostream>
 13 #include<string>
 14 #include<algorithm>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<set>
 19 #include<map>
 20 #define rep(i, n) for(int i=0;i!=n;++i)
 21 #define per(i, n) for(int i=n-1;i>=0;--i)
 22 #define Rep(i, sta, n) for(int i=sta;i!=n;++i)
 23 #define rep1(i, n) for(int i=1;i<=n;++i)
 24 #define per1(i, n) for(int i=n;i>=1;--i)
 25 #define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
 26 #define L k<<1
 27 #define R k<<1|1
 28 #define mid (tree[k].l+tree[k].r)>>1
 29 using namespace std;
 30 const int INF = 0x3f3f3f3f;
 31 typedef long long ll;
 32 
 33 inline int read() {
 34     char c=getchar();int x=0,f=1;
 35     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
 36     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
 37     return x*f;
 38 }
 39 // -----------------------------------------------------
 40 const int MAXN = 100+5;
 41 
 42 int n, m;
 43 int G[MAXN][MAXN];
 44 int vis[MAXN], dis[MAXN], pre[MAXN], used[MAXN][MAXN], path[MAXN][MAXN];
 45 
 46 inline int prim() {
 47     int ans = 0;
 48     rep1(i, n) {
 49         dis[i] = G[i][1];
 50         pre[i] = 1; vis[i] = 0;
 51         rep1(j, n) used[i][j] = path[i][j] = 0;
 52     }
 53     vis[1] = 1;
 54     rep(i, n-1) {
 55         int minn = INF;
 56         int t;
 57         rep1(j, n) {
 58             if(!vis[j] && dis[j] < minn) {
 59                 minn = dis[j];
 60                 t = j;
 61             }
 62         }
 63         vis[t] = 1;
 64         ans += minn;
 65         used[t][pre[t]] = used[pre[t]][t] = 1;
 66         rep1(j, n) {
 67             if(!vis[j] && dis[j] > G[t][j]) {
 68                 pre[j] = t;
 69                 dis[j] =  G[t][j];
 70             }
 71             if(vis[j] && j != t) {
 72                 path[j][t] = path[t][j] = max(path[j][pre[t]], minn);
 73             }
 74         }
 75     }
 76     return ans;
 77 }
 78 
 79 int main() {
 80     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
 81     int T = read();
 82     while(T--) {
 83         n = read(); m = read();
 84         rep1(i, n) rep1(j, n) G[i][j] = INF;
 85         int s, e, v;
 86         rep(i, m) {
 87             s = read(); e = read(); v = read();
 88             G[s][e] = G[e][s] = v;
 89         }
 90         int sum = prim();
 91         int ans = INF;
 92         rep1(i, n) Rep1(j, i+1, n) {
 93             if(G[i][j] != INF && !used[i][j]) {
 94                 ans = min(ans, sum-path[i][j]+G[i][j]);
 95             }
 96         }
 97         cout << sum << " " << ans << "
";
 98     }
 99     return 0;
100 }
View Code

// 如果重边 就用kruskal算法, 边的结构体中添加 int used, del; used 记录第一次最小生成树是否用了此边(为了之后枚举删除第一次用到的边); del表示是否删除该边.每次删除边之后算MST,相当于找一个边替代它,替代完之后才有可能是次小树

//因此代码很好得出

UVA 10462

  1 /*
  2  * @Promlem: 
  3  * @Time Limit: ms
  4  * @Memory Limit: k
  5  * @Author: pupil-XJ
  6  * @Date: 2019-10-21 23:48:51
  7  * @LastEditTime: 2019-10-22 00:41:56
  8  */
  9 #include<cstdio>
 10 #include<cstring>
 11 #include<cmath>
 12 #include<iostream>
 13 #include<string>
 14 #include<algorithm>
 15 #include<vector>
 16 #include<queue>
 17 #include<stack>
 18 #include<set>
 19 #include<map>
 20 #define rep(i, n) for(int i=0;i!=n;++i)
 21 #define per(i, n) for(int i=n-1;i>=0;--i)
 22 #define Rep(i, sta, n) for(int i=sta;i!=n;++i)
 23 #define rep1(i, n) for(int i=1;i<=n;++i)
 24 #define per1(i, n) for(int i=n;i>=1;--i)
 25 #define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
 26 #define L k<<1
 27 #define R k<<1|1
 28 #define mid (tree[k].l+tree[k].r)>>1
 29 using namespace std;
 30 const int INF = 0x3f3f3f3f;
 31 typedef long long ll;
 32 
 33 inline int read() {
 34     char c=getchar();int x=0,f=1;
 35     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
 36     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
 37     return x*f;
 38 }
 39 // -----------------------------------------------------
 40 const int MAXN = 100+5;
 41 const int MAXM = 200+5;
 42 
 43 struct node {
 44     int s, e, w;
 45     int used, del;
 46     bool operator < (const node &a) const {
 47         return w < a.w;
 48     }
 49 } edge[MAXM];
 50 
 51 int n, m;
 52 int fa[MAXN];
 53 bool First;
 54 
 55 inline int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
 56 
 57 inline int krustra() {
 58     int sum = 0;
 59     int cnt = 1;
 60     rep1(i, n) fa[i] = i;
 61     rep(i, m) {
 62         if(cnt == n) break;
 63         if(edge[i].del) continue;
 64         int xf = find(edge[i].s);
 65         int yf = find(edge[i].e);
 66         if(xf != yf) {
 67             fa[xf] = yf;
 68             sum += edge[i].w;
 69             ++cnt;
 70             if(First) edge[i].used = 1;
 71         }
 72     }
 73     if(cnt != n) return -1;
 74     return sum;
 75 }
 76 
 77 int main() {
 78     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
 79     int T = read();
 80     int cnt = 1;
 81     while(T--) {
 82         n = read(); m = read();
 83         int s, e, v;
 84         rep(i, m) {
 85             edge[i].s = read();
 86             edge[i].e = read();
 87             edge[i].w = read();
 88             edge[i].used = edge[i].del = 0;
 89         }
 90         cout << "Case #" << cnt++ << " : ";
 91         sort(edge, edge+m);
 92         First = true;
 93         int sum = krustra();
 94         First = false;
 95         if(sum == -1) cout << "No way
";
 96         else {
 97             int ans = INF;
 98             rep(i, m) {
 99                 if(edge[i].used) {
100                     edge[i].del = 1;
101                     int t = krustra();
102                     edge[i].del = 0;
103                     if(t != -1) ans = min(ans, t);
104                 }
105             }
106             if(ans == INF) cout << "No second way
";
107             else cout << ans << "
";
108         }
109     }
110     return 0;
111 }
View Code
原文地址:https://www.cnblogs.com/pupil-xj/p/11717459.html