zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    hdu 3854 Glorious Array(一般)
    sublime常用设置以及使用技巧
    windows下通过bat脚本调用sql脚本
    数据库操作之间的校验以及常见操作
    oracle linux、centos、redhat7配置网易云的yum源
    redhat,centos、oracle linux配置本地yum源
    查询触发器及其相关的触发器函数与表
    postgresql触发器
    root用户ssh可以登录,xftp通过sftp不能登录链接CentOS解决办法
    PG数据库中表所占用空间大小查询
  • 原文地址:https://www.cnblogs.com/cychester/p/9695734.html
Copyright © 2011-2022 走看看