次小生成树
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\n", ans + mn); 153 return 0; 154 }
#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; } } }