Luogu 4234 最小差值生成树

Solution

将边从小到大排序, 添新边$(u, v)$时 若$u,v$不连通则直接添, 若连通则 把链上最小的边去掉 再添边。

若已经加入了 $N - 1$条边则更新答案。

Code

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define rd read()
  5 using namespace std;
  6 
  7 const int N = 1e5 + 5;
  8 const int inf = 1e9;
  9 
 10 int n, m, ans = inf;
 11 int vis[N << 2];
 12 
 13 struct edge {
 14     int u, v, w;
 15 }e[N << 1];
 16 
 17 int cmp(const edge &A, const edge &B) {
 18     return A.w < B.w;
 19 }
 20 
 21 int read() {
 22     int X = 0, p = 1; char c = getchar();
 23     for (; c > '9' || c < '0'; c = getchar())
 24         if (c == '-') p = -1;
 25     for (; c >= '0' && c <= '9'; c = getchar())
 26         X = X * 10 + c - '0';
 27     return X * p;
 28 }
 29 
 30 void cmin(int &A, int B) {
 31     if (A > B)
 32         A = B;
 33 }
 34 
 35 namespace LCT {
 36     int val[N << 2], ch[N << 2][2], f[N << 2], mx[N << 2], tun[N << 2];
 37 #define lc(x) ch[x][0]
 38 #define rc(x) ch[x][1]
 39     
 40     int isroot(int x) {
 41         return lc(f[x]) != x && rc(f[x]) != x;
 42     }
 43 
 44     int get(int x) {
 45         return rc(f[x]) == x;
 46     }
 47 
 48     void up(int x) {
 49         mx[x] = val[x];
 50         if (e[mx[lc(x)]].w < e[mx[x]].w) mx[x] = mx[lc(x)];
 51         if (e[mx[rc(x)]].w < e[mx[x]].w) mx[x] = mx[rc(x)];
 52     }
 53 
 54     void rev(int x) {
 55         swap(lc(x), rc(x));
 56         tun[x] ^= 1;
 57     }
 58 
 59     void pushdown(int x) {
 60         if (tun[x]) {
 61             if (lc(x)) rev(lc(x));
 62             if (rc(x)) rev(rc(x));
 63             tun[x] = 0;
 64         }
 65     }
 66 
 67 int st[N << 2], tp;
 68 
 69     void pd(int x) {
 70         while (!isroot(x)) {
 71             st[++tp] = x;
 72             x = f[x];
 73         }
 74         pushdown(x);
 75         while (tp) pushdown(st[tp--]);
 76     }
 77 
 78     void rotate(int x) {
 79         int old = f[x], oldf = f[old], son = ch[x][get(x) ^ 1];
 80         if (!isroot(old)) ch[oldf][get(old)] = x;
 81         ch[x][get(x) ^ 1] = old;
 82         ch[old][get(x)] = son;
 83         f[old] = x; f[x] = oldf; f[son] = old;
 84         up(old); up(x);
 85     }
 86 
 87     void splay (int x) {
 88         pd(x);
 89         for (; !isroot(x); rotate(x))
 90             if (!isroot(f[x]))
 91                 rotate(get(f[x]) == get(x) ? f[x] : x);
 92     }
 93 
 94     void access(int x) {
 95         for (int y = 0; x; y = x, x = f[x]) 
 96             splay(x), ch[x][1] = y, up(x);
 97     }
 98 
 99     void mroot(int x) {
100         access(x); splay(x); rev(x);
101     }
102 
103     void split(int x, int y) {
104         mroot(x); access(y); splay(y);
105     }
106     
107     int findr(int x) {
108         access(x); splay(x);
109         while (lc(x)) pushdown(x), x = lc(x);
110         return x;
111     }
112 
113     void link(int x, int y) {
114         mroot(x); f[x] = y;
115     }
116 
117     void cut(int x, int y) {
118         split(x, y);
119         f[x] = ch[y][0] = 0;
120     }
121 }
122 using namespace LCT;
123 
124 int main()
125 {
126     n = rd; m = rd;
127     e[0].w = inf;
128     for (int i = 1;  i <= m; ++i) {
129         e[i].u = rd; e[i].v = rd; e[i].w = rd;
130     }
131     sort(e + 1, e + 1 + m, cmp);
132     for (int i = 1; i <= m; ++i)
133         val[i + n] = i;
134     for (int i = 1, l = 1, tot = 0; i <= m; ++i) {
135         int x = e[i].u, y = e[i].v;
136         if (x == y) continue;
137         mroot(x);
138         if (findr(y) != x) {
139             link(i + n, y);
140             link(i + n, x);
141             vis[i] = 1;
142             tot++;
143             if (tot == n - 1) {
144                 while (!vis[l]) l++;
145                 cmin(ans, e[i].w - e[l].w);
146             }
147         }
148         else {
149             int t = mx[y];
150             cut(t + n, e[t].u);
151             cut(t + n, e[t].v);
152             link(i + n, x);
153             link(i + n, y);
154             vis[t] = 0; vis[i] = 1;
155             if (tot == n - 1) {
156                 while (!vis[l]) l++;
157                 cmin(ans, e[i].w - e[l].w);
158             }
159         }
160     }
161     printf("%d
", ans);
162 }
View Code
原文地址:https://www.cnblogs.com/cychester/p/9695734.html