• HDU 5458 Stability (树链剖分+并查集+set)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458

    给你n个点,m条边,q个操作,操作1是删边,操作2是问u到v之间的割边有多少条。

    这题要倒着做才容易,倒着加边。

    因为这题最后保证所有的点一定连通,所以可以构建一棵树,树链剖分一下。要是u到v之间只有一条边,那便是一条割边。而加边的话,就是将u到v之间的边权都+1,边权等于1的话是桥,大于1的话就不是了。所以我们初始化树的时候,可以将边权初始化为1,加边操作将边权赋值为0。求u到v的割边个数的话,就是求u到v的和。

    中间存边我用multiset( map 超时),然后用并查集判断是不是一棵完整的树从而看情况加边。

      1 //#pragma comment(linker, "/STACK:102400000, 102400000")
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstdlib>
      5 #include <cstring>
      6 #include <cstdio>
      7 #include <vector>
      8 #include <cmath>
      9 #include <ctime>
     10 #include <list>
     11 #include <set>
     12 #include <map>
     13 using namespace std;
     14 typedef long long LL;
     15 typedef pair <int, int> P;
     16 const int N = 1e5 + 5;
     17 struct Edge {
     18     int next, to;
     19 }edge[N << 1];
     20 multiset <P> myset; //存 构建的树的边
     21 int head[N], tot;
     22 int pre[N], son[N], dep[N], size[N], cnt; //son:重儿子
     23 int top[N], id[N];
     24 int uu[N], vv[N], c[N]; //q个操作c uu vv
     25 int x[N], y[N]; //开始输入的m条边x y
     26 int ans[N]; //答案
     27 int par[N]; //并查集
     28 
     29 void init(int n) {
     30     for(int i = 1; i <= n; ++i) {
     31         par[i] = i;
     32         head[i] = -1;
     33     }
     34     tot = cnt = 0;
     35     myset.clear();
     36 }
     37 
     38 inline void add(int u, int v) {
     39     edge[tot].next = head[u];
     40     edge[tot].to = v;
     41     head[u] = tot++;
     42 }
     43 
     44 inline int search(int n) {
     45     if(n == par[n])
     46         return n;
     47     return par[n] = search(par[n]);
     48 }
     49 
     50 void dfs1(int u, int p, int d) {
     51     dep[u] = d, size[u] = 1, son[u] = u, pre[u] = p;
     52     for(int i = head[u]; ~i; i = edge[i].next) {
     53         int v = edge[i].to;
     54         if(v == p)
     55             continue;
     56         dfs1(v, u, d + 1);
     57         if(size[v] >= size[son[u]])
     58             son[u] = v;
     59         size[u] += size[v];
     60     }
     61 }
     62 
     63 void dfs2(int u, int p, int t) {
     64     top[u] = t, id[u] = ++cnt;
     65     if(son[u] != u)
     66         dfs2(son[u], u, t);
     67     for(int i = head[u]; ~i; i = edge[i].next) {
     68         int v = edge[i].to;
     69         if(v == p || v == son[u])
     70             continue;
     71         dfs2(v, u, v);
     72     }
     73 }
     74 
     75 struct SegTree {
     76     int l, r, val, lazy, mid;
     77 }T[N << 2];
     78 
     79 void build(int p, int l, int r) {
     80     T[p].mid = (l + r) >> 1;
     81     T[p].l = l, T[p].r = r, T[p].lazy = 1;
     82     if(l == r) {
     83         T[p].val = 1;
     84         return ;
     85     }
     86     build(p << 1, l, T[p].mid);
     87     build((p << 1)|1, T[p].mid + 1, r);
     88     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
     89 }
     90 
     91 inline void pushdown(int p) {
     92     int ls = p << 1, rs = (p << 1)|1;
     93     T[ls].lazy = T[rs].lazy = T[ls].val = T[rs].val = 0;
     94     T[p].lazy = 1;
     95 }
     96 
     97 void update(int p, int l, int r) {
     98     if(T[p].val == 0)
     99         return ;
    100     if(T[p].l == l && T[p].r == r) {
    101         T[p].lazy = T[p].val = 0;
    102         return ;
    103     }
    104     if(!T[p].lazy) {
    105         pushdown(p);
    106     }
    107     if(r <= T[p].mid) {
    108         update(p << 1, l, r);
    109     }
    110     else if(l > T[p].mid) {
    111         update((p << 1)|1, l, r);
    112     }
    113     else {
    114         update(p << 1, l, T[p].mid);
    115         update((p << 1)|1, T[p].mid + 1, r);
    116     }
    117     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
    118 }
    119 
    120 int query(int p, int l, int r) {
    121     if(T[p].val == 0)
    122         return 0;
    123     if(T[p].l == l && T[p].r == r) {
    124         return T[p].val;
    125     }
    126     if(!T[p].lazy) {
    127         pushdown(p);
    128     }
    129     if(r <= T[p].mid) {
    130          return query(p << 1 , l , r);
    131      }
    132      else if(l > T[p].mid) {
    133          return query((p << 1)|1 , l , r);
    134      }
    135      else {
    136          return query(p << 1 , l , T[p].mid) + query((p << 1)|1 , T[p].mid + 1 , r);
    137      }
    138 }
    139 
    140 void change(int u, int v) {
    141     int fu = top[u], fv = top[v];
    142     while(fu != fv) {
    143         if(dep[fu] >= dep[fv]) {
    144             update(1, id[fu], id[u]);
    145             u = pre[fu];
    146             fu = top[u];
    147         }
    148         else {
    149             update(1, id[fv], id[v]);
    150             v = pre[fv];
    151             fv = top[v];
    152         }
    153     }
    154     if(u == v)
    155         return ;
    156     else if(dep[u] >= dep[v])
    157         update(1, id[son[v]], id[u]);
    158     else
    159         update(1, id[son[u]], id[v]);
    160 }
    161 
    162 int find(int u, int v) {
    163     int fu = top[u], fv = top[v], res = 0;
    164     while(fu != fv) {
    165         if(dep[fu] >= dep[fv]) {
    166             res += query(1, id[fu], id[u]);
    167             u = pre[fu];
    168             fu = top[u];
    169         }
    170         else {
    171             res += query(1, id[fv], id[v]);
    172             v = pre[fv];
    173             fv = top[v];
    174         }
    175     }
    176     if(u == v)
    177         return res;
    178     else if(dep[u] >= dep[v])
    179         return res + query(1, id[son[v]], id[u]);
    180     else
    181         return res + query(1, id[son[u]], id[v]);
    182 }
    183 
    184 int main()
    185 {
    186     int t, n, m, q, u, v;
    187     scanf("%d", &t);
    188     for(int ca = 1; ca <= t; ++ca) {
    189         scanf("%d %d %d", &n, &m, &q);
    190         init(n);
    191         for(int i = 1; i <= m; ++i) {
    192             scanf("%d %d", x + i, y + i);
    193             if(x[i] > y[i])
    194                 swap(x[i], y[i]);
    195             myset.insert(make_pair(x[i], y[i])); //先存边
    196         }
    197         for(int i = 1; i <= q; ++i) {
    198             scanf("%d %d %d", c + i, uu + i, vv + i);
    199             if(uu[i] > vv[i])
    200                 swap(uu[i], vv[i]);
    201             if(c[i] == 1) {
    202                 auto pos = myset.find(make_pair(uu[i], vv[i])); //去除要删的边
    203                 myset.erase(pos);
    204             }
    205         }
    206         int f = 0;
    207         for(auto i = myset.begin(); i != myset.end(); ++i) {
    208             u = search(i->first), v = search(i->second);
    209             if(u == v) { //不成环
    210                 ++f;
    211                 x[f] = i->first, y[f] = i->second; //此时的x y存的是非树也非删的边
    212                 continue;
    213             }
    214             par[u] = v;
    215             add(i->first, i->second);
    216             add(i->second, i->first);
    217         }
    218         dfs1(1, -1, 0);
    219         dfs2(1, -1, 1);
    220         printf("Case #%d:
    ", ca);
    221         build(1, 2, n);
    222         for(int i = 1; i <= f; ++i) {
    223             change(x[i], y[i]);
    224         }
    225         f = 0;
    226         for(int i = q; i >= 1; --i) {
    227             if(c[i] == 1) {
    228                 change(uu[i], vv[i]);
    229             }
    230             else {
    231                 ans[++f] = find(uu[i], vv[i]);
    232             }
    233         }
    234         for(int i = f; i >= 1; --i) {
    235             printf("%d
    ", ans[i]);
    236         }
    237     }
    238     return 0;
    239 }
    View Code

    写的我比较头痛,调试了比较久...

  • 相关阅读:
    Web 设计与开发终极资源大全(下)
    任务失败,原因是未找到“LC.exe”,或未安装正确的 Microsoft Windows SDK
    NET开发常用DLL资源下载
    sqlserver2005 sqlserver2000连接字符串的区别(NET)
    创业大讲座观后感
    工欲善其事必先利其器搭建Android平台
    Java学习很好的笔记
    Java调用jama实现矩阵运算
    MySQL的安装及使用教程
    eval解析JSON中的注意点
  • 原文地址:https://www.cnblogs.com/Recoder/p/5774848.html
Copyright © 2020-2023  润新知