• [BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)


    传送门

    WC这个题真是丧心病狂啊,就是想学习一下怎么处理边权,给我来了这么一个破题!

    ORZ hzwer 临摹黄学长代码233 但还是复杂的一匹

    理一下思路吧

    题目大意:给定一个无向图,多次删除图中的某一条边,求两点间路径最大值的最小值

    求两点间的路径最大值的最小值的话,可以求最小生成树,那么这个值就是最小生成树上两点间路径上的最大值

    但是题目要求是删除边,LCT维护最小生成树不支持删边操作,那么就离线处理,倒着加边,用LCT维护。

    就是这个离线处理是最恶心的。

    来说说如何处理边权,把边也抽象成点,那么这个点就和原来边所连的两个点相连,其中边抽象成的点点权为边权,所连接的两个点点权为 0

    给边从小到大排序,那么边所抽象成的点的序号即为 边的序号 + n (n 为原来点的个数)

    然后再将边按照它所连的两个点为关键字排序,二分查找确定所删除的边的序号。

    再按照从小到大的顺序再排回来,跑 kruskal,依次添加没有被删除的边

    最后从后往前处理询问,添加一条边的时候先判断两端点是否连通(当然此题不必,因为题目中说:任何时候我们考虑的水管网络都是连通的,即从任一结点A必有至少一条水管路径通往任一结点B。。所以肯定连通)

    然后找出两点间路径边权的最大的,判断最大的边权是否大于要加入的边的边权,如果大于,就删除这条边,连接新边,否则就不加入(维护最小生成树)

    具体细节看代码

    ——代码

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #define N 1500005
      6 #define get(x) (son[f[x]][1] == (x))
      7 #define swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
      8 #define isroot(x) (son[f[x]][0] ^ (x) && son[f[x]][1] ^ (x))
      9 
     10 int n, m, Q, tot;
     11 int mx[N], rev[N], fa[N], f[N], val[N], son[N][2], s[N];
     12 
     13 struct node
     14 {
     15     int x, y, z, id;
     16     bool d;
     17 }e[N];
     18 
     19 struct ask
     20 {
     21     int f, x, y, ans, id;
     22 }q[N];
     23 
     24 inline int read()
     25 {
     26     int x = 0, f = 1;
     27     char ch = getchar();
     28     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
     29     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
     30     return x * f;
     31 }
     32 
     33 inline bool cmp1(node x, node y)
     34 {
     35     return x.z < y.z;
     36 }
     37 
     38 inline bool cmp2(node x, node y)
     39 {
     40     return x.x < y.x || (x.x == y.x && x.y < y.y);
     41 }
     42 
     43 inline bool cmp3(node x, node y)
     44 {
     45     return x.id < y.id;
     46 }
     47 
     48 inline int getf(int x)
     49 {
     50     return x == fa[x] ? x : fa[x] = getf(fa[x]);
     51 }
     52 
     53 inline int find(int x, int y)
     54 {
     55     int l = 1, r = m, mid;
     56     while(l <= r)
     57     {
     58         mid = (l + r) >> 1;
     59         if(e[mid].x < x || (e[mid].x == x && e[mid].y < y)) l = mid + 1;
     60         else if(e[mid].x == x && e[mid].y == y) return mid;
     61         else r = mid - 1;
     62     }
     63 }
     64 
     65 inline void update(int x)
     66 {
     67     if(x)
     68     {
     69         mx[x] = x;
     70         if(son[x][0] && val[mx[son[x][0]]] > val[mx[x]]) mx[x] = mx[son[x][0]];
     71         if(son[x][1] && val[mx[son[x][1]]] > val[mx[x]]) mx[x] = mx[son[x][1]];
     72     }
     73 }
     74 
     75 inline void pushdown(int x)
     76 {
     77     if(x && rev[x])
     78     {
     79         swap(son[x][0], son[x][1]);
     80         if(son[x][0]) rev[son[x][0]] ^= 1;
     81         if(son[x][1]) rev[son[x][1]] ^= 1;
     82         rev[x] = 0;
     83     }
     84 }
     85 
     86 inline void rotate(int x)
     87 {
     88     int old = f[x], oldf = f[old], wh = get(x);
     89     
     90     if(!isroot(old))
     91         son[oldf][get(old)] = x;
     92     f[x] = oldf;
     93     
     94     son[old][wh] = son[x][wh ^ 1];
     95     f[son[old][wh]] = old;
     96     
     97     son[x][wh ^ 1] = old;
     98     f[old] = x;
     99     
    100     update(old);
    101     update(x);
    102 }
    103 
    104 inline void splay(int x)
    105 {
    106     int i, fat, t = 0;
    107     s[++t] = x;
    108     for(i = x; !isroot(i); i = f[i]) s[++t] = f[i];
    109     for(i = t; i; i--) pushdown(s[i]);
    110     for(; !isroot(x); rotate(x))
    111         if(!isroot(fat = f[x]))
    112             rotate(get(x) ^ get(fat) ? x : fat);
    113 }
    114 
    115 inline void access(int x)
    116 {
    117     for(int t = 0; x; t = x, x = f[x]) splay(x), son[x][1] = t, update(x);
    118 }
    119 
    120 inline void reverse(int x)
    121 {
    122     access(x);
    123     splay(x);
    124     rev[x] ^= 1;
    125 }
    126 
    127 inline void cut(int x, int y)
    128 {
    129     reverse(x);
    130     access(y);
    131     splay(y);
    132     son[y][0] = f[x] = 0;
    133     update(y);
    134 }
    135 
    136 inline void link(int x, int y)
    137 {
    138     reverse(x);
    139     f[x] = y;
    140     access(x);
    141 }
    142 
    143 inline int query(int x, int y)
    144 {
    145     reverse(x);
    146     access(y);
    147     splay(y);
    148     return mx[y];
    149 }
    150 
    151 int main()
    152 {
    153     int i, j, k, t, x, y, fx, fy;
    154     n = read();
    155     m = read();
    156     Q = read();
    157     for(i = 1; i <= n; i++) fa[i] = i;
    158     for(i = 1; i <= m; i++)
    159     {
    160         e[i].x = read();
    161         e[i].y = read();
    162         e[i].z = read();
    163         if(e[i].x > e[i].y) swap(e[i].x, e[i].y);
    164     }
    165     std::sort(e + 1, e + m + 1, cmp1);
    166     for(i = 1; i <= m; i++)
    167     {
    168         e[i].id = i;
    169         val[n + i] = e[i].z;
    170         mx[n + i] = n + i;
    171     }
    172     std::sort(e + 1, e + m + 1, cmp2);
    173     for(i = 1; i <= Q; i++)
    174     {
    175         q[i].f = read();
    176         q[i].x = read();
    177         q[i].y = read();
    178         if(q[i].x > q[i].y) swap(q[i].x, q[i].y);
    179         if(q[i].f == 2)
    180         {
    181             t = find(q[i].x, q[i].y);
    182             e[t].d = 1;
    183             q[i].id = e[t].id;
    184         }
    185     }
    186     std::sort(e + 1, e + m + 1, cmp3);
    187     for(i = 1; i <= m; i++)
    188         if(!e[i].d)
    189         {
    190             x = e[i].x;
    191             y = e[i].y;
    192             fx = getf(x);
    193             fy = getf(y);
    194             if(fx ^ fy)
    195             {
    196                 fa[fx] = fy;
    197                 link(x, i + n);
    198                 link(y, i + n);
    199                 tot++;
    200                 if(tot == n - 1) break;
    201             }
    202         }
    203     for(i = Q; i; i--)
    204     {
    205         if(q[i].f == 1) q[i].ans = val[query(q[i].x, q[i].y)];
    206         else
    207         {
    208             x = q[i].x;
    209             y = q[i].y;
    210             k = q[i].id;
    211             t = query(x, y);
    212             if(e[k].z < val[t])
    213             {
    214                 cut(e[t - n].x, t);
    215                 cut(e[t - n].y, t);
    216                 link(x, k + n);
    217                 link(y, k + n);
    218             }
    219         }
    220     }
    221     for(i = 1; i <= Q; i++)
    222         if(q[i].f == 1)
    223             printf("%d
    ", q[i].ans);
    224     return 0;
    225 }
    View Code
  • 相关阅读:
    大学生程序猿IT情书“2014爱的告白挑战赛”获奖名单及优秀情书展示系列之
    Codeforces 385C Bear and Prime Numbers
    CSU1659: Graph Center(最短路)
    新版ADT出现appcompat_v7的问题
    @IBDesignable和@IBInspectable
    FTP命令详解
    R语言屏幕输出
    R语言常用基础知识(入门)
    R语言数据类型转换
    使用建议(内部使用)
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/7041025.html
Copyright © 2020-2023  润新知