BZOJ 1015 并查集&连通块

  很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的
机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直
接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划
地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首
领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每
一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则
这两个星球在同一个连通块中)。

  注意加点和删点的时候连通块数量的判定即可

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int maxn = 1000005;
  5 inline void read(int &v)
  6 {
  7     v = 0;
  8     char c = 0;
  9     int p = 1;
 10     while (c < '0' || c > '9') {
 11         if (c == '-') {
 12             p = -1;
 13         }
 14         c = getchar();
 15     }
 16     while (c >= '0' && c <= '9') {
 17         v = (v << 3) + (v << 1) + c - '0';
 18         c = getchar();
 19     }
 20     v *= p;
 21 }
 22 vector<int> g[maxn];
 23 int par[maxn];
 24 int find(int x)
 25 {
 26     return par[x] == x ? x : par[x] = find(par[x]);
 27 }
 28 void unite(int x, int y)
 29 {
 30     x = find(x);
 31     y = find(y);
 32     if (x != y) {
 33         par[x] = y;
 34     }
 35 }
 36 int ans[maxn];
 37 int del[maxn];
 38 bool ok[maxn];
 39 int main()
 40 {
 41     int n, m;
 42     read(n), read(m);
 43     for (int i = 0; i <= n; i++) {
 44         par[i] = i;
 45         ok[i] = 1;
 46     }
 47     int u, v;
 48     for (int i = 1; i <= m; i++) {
 49         read(u), read(v);
 50         g[u].push_back(v);
 51         g[v].push_back(u);
 52     }
 53     int anser = 0;
 54     int q;
 55     read(q);
 56     for (int i = 1; i <= q; i++) {
 57         read(del[i]);
 58         ok[del[i]] = 0;
 59     }
 60     for (int i = 0; i < n; i++) {
 61         if (ok[i])
 62             for (int j = 0; j < g[i].size(); j++) {
 63                 v = g[i][j];
 64                 //cout << i << " to " << v << endl;
 65                 if (ok[v]) {
 66                     u = find(i), v = find(v);
 67                     if (u != v) {
 68                         unite(u, v);
 69                     }
 70                 }
 71             }
 72     }
 73     for (int i = 0; i < n; i++) {
 74         u = find(i);
 75         if (u == i && ok[i]) {
 76             anser++;
 77         }
 78     }
 79     int fu, fv;
 80     ans[q] = anser;
 81     for (int i = q - 1; i >= 0; i--) {
 82         ans[i] = ans[i + 1] + 1;
 83         u = del[i + 1];
 84         ok[u] = 1;
 85         for (int v, j = 0; j < g[u].size(); j++) {
 86             v = g[u][j];
 87             if (ok[v]) {
 88                 fu = find(u), fv = find(v);
 89                 if (fu != fv) {
 90                     ans[i]--;
 91                     unite(fu, fv);
 92                 }
 93             }
 94         }
 95     }
 96     for (int i = 0; i <= q; i++) {
 97         printf("%d\n", ans[i]);
 98     }
 99     return 0;
100 }
View Code

 

posted @ 2018-12-07 08:38  Aragaki  阅读(224)  评论(0编辑  收藏  举报