[P4234] Luo Gu minimum difference Spanning Tree

Description

Given an n points, without edges to FIG. M, the minimum spanning tree is obtained the maximum and minimum edge weight difference

Solution

LCT + disjoint-set

Accordance with the idea of ​​the minimum spanning tree, first side from small to large sorted by the right side, then the order of consideration of each edge

If the current two endpoints of this edge is not connected, then direct communication

If the two endpoints have connectivity, we will add this edge to form a ring, then in order to make "the right side of the difference between the maximum and minimum" as small as possible, we can be on one side of the ring shortest delete this, change to this side (apparently right)

LCT achieved by maintaining the minimum, even short sides of the basic operation is the LCT

When the current side is already a tree to complete the update answer

Code

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int N = 50010;
  5 const int M = 200010;
  6 inline int read() {
  7     int ret = 0, op = 1;
  8     char c = getchar();
  9     while (!isdigit(c)) {
 10         if (c == '-') op = -1; 
 11         c = getchar();
 12     }
 13     while (isdigit(c)) {
 14         ret = (ret << 3) + (ret << 1) + c - '0';
 15         c = getchar();
 16     }
 17     return ret * op;
 18 }
 19 struct Edge {
 20     int from, to, dis;
 21     bool operator <(const Edge &x) const {
 22         return dis < x.dis;
 23     }
 24 } edge[M];
 25 struct LCT {
 26     int fa, val, minn, ch[2], tag;
 27 } a[N + M];
 28 int n, m, s[N + M], f[N];
 29 int vis[M];
 30 int find(int x) {
 31     if (f[x] != x) return f[x] = find(f[x]);
 32     return f[x];
 33 }
 34 inline int isnroot(int now) {
 35     return a[a[now].fa].ch[0] == now || a[a[now].fa].ch[1] == now;
 36 }
 37 inline int get(int x, int y) {
 38     return a[x].val < a[y].val ? x : y;
 39 }
 40 inline void update(int now) {
 41     int l = a[now].ch[0];
 42     int r = a[now].ch[1];
 43     a[now].minn = get(now, get(a[l].minn, a[r].minn));
 44 } 
 45 inline void rev(int now) {
 46     swap(a[now].ch[0], a[now].ch[1]);
 47     a[now].tag ^= 1;
 48 }
 49 inline void pushdown(int now) {
 50     if (a[now].tag) {
 51         if (a[now].ch[0]) rev(a[now].ch[0]);
 52         if (a[now].ch[1]) rev(a[now].ch[1]);
 53         a[now].tag = 0;
 54     }
 55 }
 56 void rotate(int x) {
 57     int y = a[x].fa;
 58     int z = a[y].fa;
 59     int xson = a[y].ch[1] == x;
 60     int yson = a[z].ch[1] == y;
 61     int B = a[x].ch[xson ^ 1];
 62     if (isnroot(y)) a[z].ch[yson] = x;
 63     a[x].ch[xson ^ 1] = y;
 64     a[y].ch[xson] = B;
 65     if (B) a[B].fa = y;
 66     a[y].fa = x;
 67     a[x].fa = z;
 68     update(y);
 69 }
 70 void splay(int x) {
 71     int y = x, z = 0;
 72     s[++z] = y;
 73     while (isnroot(y)) y = a[y].fa, s[++z] = y;
 74     while (z) pushdown(s[z--]);
 75     while (isnroot(x)) {
 76         y = a[x].fa;
 77         z = a[y].fa;
 78         if (isnroot(y))
 79             (a[z].ch[0] == y) ^ (a[y].ch[0] == x) ? rotate(x) : rotate(y);
 80         rotate(x);
 81     }
 82     update(x);
 83 }
 84 void access(int x) {
 85     for (register int y = 0; x; y = x, x = a[x].fa) {
 86         splay(x); a[x].ch[1] = y; update(x);
 87     }
 88 }
 89 void makeroot(int x) {
 90     access(x);
 91     splay(x);
 92     rev(x);
 93 }
 94 void link(int i) {
 95     makeroot(edge[i].from);
 96     a[edge[i].from].fa = i + N;
 97     a[i + N].fa = edge[i].to;
 98 }
 99 void cut(int i) {
100     access(edge[i - N].from);
101     splay(i);
102     a[a[i].ch[1]].fa = a[a[i].ch[0]].fa = 0;
103     a[i].ch[0] = a[i].ch[1] = 0;
104 }
105 int main() {
106     n = read(); m = read();
107     for (register int i = 0; i <= n; ++i) f[i] = i, a[i].val = 2147483647;
108     for (register int i = 1; i <= m; ++i) {
109         edge[i].from = read(); edge[i].to = read(); edge[i].dis = read();
110     }
111     sort(edge + 1, edge + m + 1);
112     int sum = 0, ans = 0, k = 1;
113     for (register int i = 1; i <= m; ++i) {
114         a[i + N].val = edge[i].dis;
115         int x = edge[i].from;
116         int y = edge[i].to;
117         if (find(x) != find(y)) {
118             vis[i] = 1;
119             sum++;
120             link(i);
121             f[f[x]] = f[y];
122             if (sum == n - 1) ans = edge[i].dis - edge[k].dis;
123         }
124         else {
125             if (x == y) continue ;
126             vis[i] = 1;
127             makeroot(x);
128             access(y); splay(y);
129             vis[a[y].minn - N] = 0;
130             while (vis[k] == 0) ++k;
131             cut(a[y].minn); link(i);
132             if (sum == n - 1) ans = min(ans, edge[i].dis - edge[k].dis);
133         }
134     }
135     printf("%d\n", ans);
136     return 0;
137 }
AC Code

 

Guess you like

Origin www.cnblogs.com/shl-blog/p/11354557.html