• bzoj 3237 连通图


    Input

    Output

    Sample Input

    4 5
    1 2
    2 3
    3 4
    4 1
    2 4
    3
    1 5
    2 2 3
    2 1 2

    Sample Output

    Connected
    Disconnected
    Connected

    Hint

    N<=100000 M<=200000 K<=100000


      题目大意 给出一个有n个节点和m条边的图,然后有k个询问,每个询问是删掉一些边,然后判断图是否连通,询问之间互相独立。

      连通性问题通常的做法是并查集,然而并查集不支持删边,但是可以撤销上次操作,所以只能考虑把一条一条边加入并查集,为了高效的确定边是否存在,可以用一个时间戳(其实就是确定某条边在询问时是否存在)。因为存在的时间段是连续的,所以呢就用一个线段树,每个点开一个vector,记录恰好存在时间段为当前区间的的边有哪些。

      接着开始遍历整棵树,每到一个点就把它存的边一一塞进并查集

      1)如果不是叶节点,然后访问左右子树,访问完后O(1)撤销这个点加入的所有边

      2)如果是叶节点,就随便找个点的最高级father(就是f[father] = father)看下它的size是否为n(然后一个操作就"水"完了)

      因为并查集要支持撤销,所以不能压缩路径了,只能按秩合并(把小的合并到大的中)。

      注意题目输入中的数据范围是错的(然后我就RE了一次)

    Code

      1 /**
      2  * bzoj
      3  * Problem#3237
      4  * Accepted
      5  * Time:19508ms
      6  * Memory:72656k
      7  */
      8 #include <iostream>
      9 #include <cstdio>
     10 #include <ctime>
     11 #include <cmath>
     12 #include <cctype>
     13 #include <cstring>
     14 #include <cstdlib>
     15 #include <fstream>
     16 #include <sstream>
     17 #include <algorithm>
     18 #include <map>
     19 #include <set>
     20 #include <stack>
     21 #include <queue>
     22 #include <vector>
     23 #include <stack>
     24 #ifndef WIN32
     25 #define Auto "%lld"
     26 #else
     27 #define Auto "%I64d"
     28 #endif
     29 using namespace std;
     30 typedef bool boolean;
     31 const signed int inf = (signed)((1u << 31) - 1);
     32 const signed long long llf = (signed long long)((1ull << 63) - 1);
     33 const double eps = 1e-6;
     34 const int binary_limit = 128;
     35 #define smin(a, b) a = min(a, b)
     36 #define smax(a, b) a = max(a, b)
     37 #define max3(a, b, c) max(a, max(b, c))
     38 #define min3(a, b, c) min(a, min(b, c))
     39 template<typename T>
     40 inline boolean readInteger(T& u){
     41     char x;
     42     int aFlag = 1;
     43     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     44     if(x == -1) {
     45         ungetc(x, stdin);    
     46         return false;
     47     }
     48     if(x == '-'){
     49         x = getchar();
     50         aFlag = -1;
     51     }
     52     for(u = x - '0'; isdigit((x = getchar())); u = (u * 10) + x - '0');
     53     ungetc(x, stdin);
     54     u *= aFlag;
     55     return true;
     56 }
     57 
     58 typedef class SegTreeNode {
     59     public:
     60         vector< pair<int, int> > e;
     61         SegTreeNode *l, *r;
     62         
     63         SegTreeNode() {        }
     64         SegTreeNode(SegTreeNode* l, SegTreeNode* r):l(l), r(r) {        }
     65 }SegTreeNode;
     66 
     67 SegTreeNode pool[400000];
     68 SegTreeNode *top = pool;
     69 SegTreeNode null = SegTreeNode(&null, &null);
     70 
     71 inline SegTreeNode* newnode() {
     72     *top = SegTreeNode(&null, &null);
     73     return top++;
     74 }
     75 
     76 typedef class union_found {
     77     public:
     78         int n;
     79         SegTreeNode* root;
     80         int* f;
     81         int* s;
     82         stack< pair<int, int> > trace;
     83         stack< pair<int, int> > ss;
     84         union_found():root(NULL) {        }
     85         union_found(int n):root(&null), n(n) {
     86             f = new int[(n + 1)];
     87             s = new int[(n + 1)];
     88             fill(s, s + n + 1, 1);
     89             for(int i = 0; i <= n; i++)
     90                 f[i] = i;
     91         }
     92         
     93         int find(int x) {
     94             return (f[x] == x) ? (x) : (find(f[x]));
     95         }
     96         
     97         inline void unit(int fa, int so) {
     98             int ffa = find(fa);
     99             int fso = find(so);
    100             if(ffa == fso)    trace.push(pair<int, int>(0, 0));
    101             else {
    102                 if(s[ffa] < s[fso])
    103                     swap(ffa, fso);
    104                 trace.push(pair<int, int>(fso, f[fso]));
    105                 ss.push(pair<int, int>(ffa, s[ffa]));
    106                 s[ffa] += s[fso];
    107                 f[fso] = ffa;
    108             }
    109         }
    110         
    111         inline void undo() {
    112             pair<int, int> p = trace.top();
    113             pair<int, int> sp = ss.top();
    114             trace.pop();
    115             if(p.first == 0)    return;
    116             f[p.first] = p.second;
    117             s[sp.first] = sp.second;
    118             ss.pop();
    119         }
    120         
    121         void update(SegTreeNode*& node, int l, int r, int ql, int qr, pair<int, int> &val) {
    122             if(node == &null)    node = newnode();
    123             if(l == ql && r == qr) {
    124 //                printf("Update at segment [%d, %d] with the edge (%d, %d)
    ", l, r, val.first, val.second);
    125                 node->e.push_back(val);
    126                 return;
    127             }
    128             int mid = (l + r) >> 1;
    129             if(qr <= mid)    update(node->l, l, mid, ql, qr, val);
    130             else if(ql > mid)    update(node->r, mid + 1, r, ql, qr, val);
    131             else {
    132                 update(node->l, l, mid, ql, mid, val);
    133                 update(node->r, mid + 1, r, mid + 1, qr, val);
    134             }
    135         }
    136         
    137         void query(SegTreeNode* node, int l, int r, boolean *res) {
    138             pair<int, int> p;
    139             for(int i = 0; i < (signed)node->e.size(); i++) {
    140                 p = node->e[i];
    141                 unit(p.first, p.second);
    142 //                printf("Connect %d and %d
    ", p.first, p.second);
    143             }
    144             if(l == r) {
    145                 res[l] = (s[find(1)] == n);
    146             } else {
    147                 int mid = (l + r) >> 1;
    148                 query(node->l, l, mid, res);
    149                 query(node->r, mid + 1, r, res);
    150             }
    151             for(int i = 0; i < (signed)node->e.size(); i++)
    152                 undo();
    153         }
    154 }union_found;
    155 
    156 int n, m, q;
    157 pair<int, int> *es;
    158 vector<int> *exists;
    159 union_found uf;
    160 
    161 inline void init() {
    162     readInteger(n);
    163     readInteger(m);
    164     es = new pair<int, int>[(m + 1)];
    165     for(int i = 1; i <= m; i++) {
    166         readInteger(es[i].first);
    167         readInteger(es[i].second);
    168     }
    169     exists = new vector<int>[(m + 1)];
    170     readInteger(q);
    171     for(int i = 1, c, x; i <= q; i++) {
    172         readInteger(c);
    173         while(c--) {
    174             readInteger(x);
    175             exists[x].push_back(i);
    176         }
    177     }
    178 }
    179 
    180 inline void mktree() {
    181     uf = union_found(n);
    182     for(int i = 1; i <= m; i++) {
    183         exists[i].push_back(q + 1);
    184         for(int j = 0, last = 1; j < (signed)exists[i].size(); j++) {
    185             if(last == exists[i][j])
    186                 last++;
    187             else {
    188 //                cout << exists[i][j] << endl;
    189                 uf.update(uf.root, 1, q, last, exists[i][j] - 1, es[i]);
    190                 last = exists[i][j] + 1;
    191             }
    192         }
    193     }
    194 }
    195 
    196 boolean *res;
    197 inline void solve() {
    198     res = new boolean[(q + 1)];
    199     uf.query(uf.root, 1, q, res);
    200     for(int i = 1; i <= q; i++)
    201         puts((res[i]) ? ("Connected") : ("Disconnected"));
    202 }
    203 
    204 int main() {
    205     init();
    206     mktree();
    207     solve();
    208     return 0;
    209 }
  • 相关阅读:
    恭喜,贺喜,同喜
    IIS 原理学习
    ASP.NET Ajax 学习(一)服务器端部分
    一张图片引发的血案
    poj 2828 Buy Tickets
    hdu 1556 Color the ball
    nyoj 求余数
    hdu 1358Period
    hdu 3577Fast Arrangement
    poj2752 Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7201307.html
Copyright © 2020-2023  润新知