次小生成树

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int inf=0x3f3f3f3f;
  4 typedef long long ll;
  5 const int M=300001;
  6 const int N=100001;
  7 struct node {
  8     int u, v, w, k;
  9     bool operator<(const node &b) const {
 10         return w < b.w;
 11     }
 12 }a[M];
 13 struct node1 {
 14     int to,next,w;
 15 }e[M];
 16 int n,m,mn=inf,t,head[N],f[N][20],d1[N][20],d2[N][20],deep[N];
 17 
 18 void add(int u,int v,int w){
 19     t++;
 20     e[t].to=v;
 21     e[t].w=w;
 22     e[t].next=head[u];
 23     head[u]=t;
 24 }
 25 
 26 struct Kurskal {
 27     int n, m,f[N];
 28     int find(int x) {
 29         return x == f[x] ? x : f[x] = find(f[x]);
 30     }
 31 
 32     ll kurskal() {
 33         int k = 0;
 34         ll ans=0;
 35         sort(a + 1, a + m + 1);
 36         for (int i = 1; i <= m; i++) {
 37             int x = find(a[i].u), y = find(a[i].v);
 38             if (x != y) {
 39                 ans += a[i].w;
 40                 a[i].k=1;
 41                 add(a[i].u, a[i].v, a[i].w);
 42                 add(a[i].v, a[i].u, a[i].w);
 43                 f[x] = y;
 44                 k++;
 45                 if (k == n - 1) {
 46                     break;
 47                 }
 48             }
 49         }
 50         return ans;
 51     }
 52 
 53     void init(int n, int m) {
 54         this->n = n;
 55         this->m = m;
 56         for (int i = 1; i <= n; i++) {
 57             f[i] = i;
 58         }
 59         for (int i = 1; i <= m; i++) {
 60             scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);
 61         }
 62     }
 63 } K;
 64 
 65 
 66 void dfs(int x,int fa) {
 67     for (int i = 1; i <= 16; i++) {
 68         if (deep[x] < (1 << i)) break;
 69         f[x][i] = f[f[x][i - 1]][i - 1];
 70         d1[x][i] = max(d1[x][i - 1], d1[f[x][i - 1]][i - 1]);
 71         if (d1[x][i - 1] == d1[f[x][i - 1]][i - 1]) {
 72             d2[x][i] = max(d2[x][i - 1], d2[f[x][i - 1]][i - 1]);
 73         } else {
 74             d2[x][i] = min(d1[x][i - 1], d1[f[x][i - 1]][i - 1]);
 75             d2[x][i] = max(d2[x][i - 1], d2[x][i]);
 76             d2[x][i] = max(d2[x][i], d2[f[x][i - 1]][i - 1]);
 77         }
 78     }
 79     for (int i = head[x]; i; i = e[i].next) {
 80         int to = e[i].to;
 81         if (to != fa) {
 82             f[to][0] = x;
 83             d1[to][0] = e[i].w;
 84             deep[to] = deep[x] + 1;
 85             dfs(to, x);
 86         }
 87     }
 88 }
 89 
 90 
 91 int lca(int x,int y) {
 92     if (deep[x] < deep[y]) {
 93         swap(x, y);
 94     }
 95     int h = deep[x] - deep[y], k = 0;
 96     while (h) {
 97         if (h & 1) {
 98             x = f[x][k];
 99         }
100         h >>= 1;
101         k++;
102     }
103     if (x == y) {
104         return x;
105     }
106     for (int k = 19; k >= 0; k--) {
107         if (f[x][k] != f[y][k]) {
108             x = f[x][k];
109             y = f[y][k];
110         }
111     }
112     return f[x][0];
113 }
114 
115 
116 void cal(int x,int fa,int v) {
117     int mx1 = 0,mx2 = 0;
118     int h = deep[x] - deep[fa];
119     for (int i = 0; i <= 16; i++) {
120         if (h & (1 << i)) {
121             if (d1[x][i] > mx1) {
122                 mx2 = mx1;
123                 mx1 = d1[x][i];
124             }
125             mx2 = max(mx2, d2[x][i]);
126             x = f[x][i];
127         }
128     }
129     if (mx1 != v) {
130         mn = min(mn, v - mx1);
131     } else {
132         mn = min(mn, v - mx2);
133     }
134 }
135 
136 void solve(int i,int v){
137     int x=a[i].u,y=a[i].v,f=lca(x,y);
138     cal(x,f,v);
139     cal(y,f,v);
140 }
141 
142 int main() {
143     scanf("%d%d", &n, &m);
144     K.init(n,m);
145     ll ans = K.kurskal();
146     dfs(1, 0);
147     for (int i = 1; i <= m; i++) {
148         if (!a[i].k) {
149             solve(i, a[i].w);
150         }
151     }
152     printf("%lld
", ans + mn);
153     return 0;
154 }
View Code
#include<bits/stdc++.h>

次小生成树
求最小生成树时用数组Max[i][j]来表示MST中i到j最大边权
求完后直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案

int prim(int cost[][maxn],int n) {
    int ans = 0;
    memset(vis, 0, sizeof(vis));
    memset(Max, 0, sizeof(Max));
    memset(used, 0, sizeof(used));
    v[0] = 1;
    pre[0] = -1;
    for (int i = 1; i <= n; i++) {
        lowc[i] = cost[0][i];
        pre[i] = 0;
    }
    lowc[0] = 0;
    for (int i = 1; i < n; i++) {
        int minc = inf;
        int p = -1;
        for (int j = 0; j < n; j++) {
            if (!vis[j] && minc > lowc[j]) {
                minc = lowc[j];
                p = j;
            }
        }
        if (minc == inf) {
            return -1;
        }
        ans += minc;
        vis[p] = 1;
        used[p][pre[p]] = used[pre[p]][p] = 1;
        for (int j = 0; j < n; j++) {
            if (vis[j] && j != p) {
                Max[j][p] = Max[p][j] = max(Max[j][pre[p]], lowc[p]);
            }
            if (!vis[j] && lowc[j] > cost[p][j]) {
                lowc[j] = cost[p][j];
                pre[j] = p;
            }
        }
    }
    return ans;
}
        
    }
}

  

原文地址:https://www.cnblogs.com/Accpted/p/11233130.html