BZOJ 3237: [Ahoi2013]连通图

3237: [Ahoi2013]连通图

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1161  Solved: 399
[Submit][Status][Discuss]

Description

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

 

Source

 
[Submit][Status][Discuss]

 

很有意思的一道题。乍一看就是LCT,后来听说可以CDQ水过,一想确实哎,写写就1A了。

 

对于一张图的连通性,我们可以用并查集维护,简单方便,可是不支持删边操作(这里指的是随机的删边)。但发现可以通过记录father数组的更改,得到一个回溯栈,方便地进行顺序删边。

利用CDQ分治的想法,在一个solve(l,r)时,考虑把(mid,r]内的边补回到图中,维护并查集并记录改变(用来回溯),然后递归solve(l,mid),最后回溯;再把[l,mid]的边补回,递归右侧,回溯。这样到底层solve(l,r),即l==r时,并查集维护的刚好不包含当前这组询问中的边,此时记录下答案即可。

 

  1 #include <bits/stdc++.h>
  2 
  3 inline int getC(void) {
  4     static const int siz = 1024;
  5     
  6     static char buf[siz];
  7     static char *hd = buf + siz;
  8     static char *tl = buf + siz;
  9     
 10     if (hd == tl)
 11         fread(hd = buf, 1, siz, stdin);
 12     
 13     return int(*hd++);
 14 }
 15 
 16 inline int getI(void) {
 17     register int ret = 0;
 18     register int neg = false;
 19     register int bit = getC();
 20     
 21     for (; bit < 48; bit = getC())
 22         if (bit == '-')neg ^= true;
 23 
 24     for (; bit > 47; bit = getC())
 25         ret = ret * 10 + bit - '0';
 26     
 27     return neg ? -ret : ret;
 28 }
 29 
 30 const int maxn = 500005;
 31 
 32 int n, m, p;
 33 
 34 struct edge {
 35     int x, y; 
 36 }e[maxn];
 37 
 38 struct query {
 39     int k, s[5];
 40     bool connect;
 41 }q[maxn];
 42 
 43 int fa[maxn];
 44 int sz[maxn];
 45 
 46 int cnt[maxn];
 47 
 48 inline int find(int u) {
 49     while (fa[u] != u)
 50         u = fa[u];
 51     return u;
 52 }
 53 
 54 int stk[maxn], tot;
 55 
 56 void solve(int l, int r) {
 57     if (l == r) {
 58         q[l].connect = sz[find(1)] == n;
 59         return;
 60     }
 61     
 62     int mid = (l + r) >> 1, top = tot;
 63     
 64     for (int i = l; i <= mid; ++i)
 65         for (int j = 1; j <= q[i].k; ++j)
 66             if (--cnt[q[i].s[j]] == 0) {
 67                 int x = find(e[q[i].s[j]].x);
 68                 int y = find(e[q[i].s[j]].y);
 69                 if (x != y) {
 70                     if (sz[x] < sz[y])
 71                         fa[x] = y, sz[y] += sz[x], stk[++tot] = x;
 72                     else
 73                         fa[y] = x, sz[x] += sz[y], stk[++tot] = y;
 74                 }
 75             }
 76     
 77     solve(mid + 1, r);
 78     
 79     while (tot > top) {
 80         int t = stk[tot--];
 81         sz[fa[t]] -= sz[t];
 82         fa[t] = t;
 83     }
 84     
 85     for (int i = l; i <= mid; ++i)
 86         for (int j = 1; j <= q[i].k; ++j)
 87             ++cnt[q[i].s[j]];
 88     
 89     for (int i = mid + 1; i <= r; ++i)
 90         for (int j = 1; j <= q[i].k; ++j)
 91             if (--cnt[q[i].s[j]] == 0) {
 92                 int x = find(e[q[i].s[j]].x);
 93                 int y = find(e[q[i].s[j]].y);
 94                 if (x != y) {
 95                     if (sz[x] < sz[y])
 96                         fa[x] = y, sz[y] += sz[x], stk[++tot] = x;
 97                     else
 98                         fa[y] = x, sz[x] += sz[y], stk[++tot] = y;
 99                 }
100             }
101     
102     solve(l, mid);
103     
104     while (tot > top) {
105         int t = stk[tot--];
106         sz[fa[t]] -= sz[t];
107         fa[t] = t;
108     }
109     
110     for (int i = mid + 1; i <= r; ++i)
111         for (int j = 1; j <= q[i].k; ++j)
112             ++cnt[q[i].s[j]];
113 }
114 
115 signed main(void) {
116     n = getI();
117     m = getI();
118     
119     for (int i = 1; i <= n; ++i)
120         fa[i] = i, sz[i] = 1;
121         
122     for (int i = 1; i <= m; ++i)
123         e[i].x = getI(),
124         e[i].y = getI();
125         
126     p = getI();
127     
128     for (int i = 1; i <= p; ++i) {
129         q[i].k = getI();
130         for (int j = 1; j <= q[i].k; ++j)
131             ++cnt[q[i].s[j] = getI()];
132     }
133     
134     for (int i = 1; i <= m; ++i)
135         if (!cnt[i]) {
136             int x = find(e[i].x);
137             int y = find(e[i].y);
138             if (x != y) {
139                 if (sz[x] < sz[y])
140                     fa[x] = y, sz[y] += sz[x];
141                 else
142                     fa[y] = x, sz[x] += sz[y];
143             }
144         }
145         
146     solve(1, p);
147     
148     for (int i = 1; i <= p; ++i)
149         puts(q[i].connect ? "Connected" : "Disconnected");
150 }

 

@Author: YouSiki

 

posted @ 2017-01-02 19:25  YouSiki  阅读(660)  评论(1编辑  收藏  举报