逆向并查集 HYSBZ1015星球大战starwar

 星球大战starwar

 HYSBZ - 1015 
 

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

Input

  输入文件第一行包含两个整数,N (1  < =  N  < =  2M) 和M (1  < =  M  < =  200,000),分别表示星球的
数目和以太隧道的数目。星球用 0 ~ N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0 < = X <> 
Y 表示星球x和星球y之间有“以太”隧道,可以直接通讯。接下来的一行为一个整数k,表示将遭受攻击的星球的
数目。接下来的k行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这k个数互不相同,且都在0到n-1的范
围内。

Output

  输出文件的第一行是开始时星球的连通块个数。接下来的N行,每行一个整数,表示经过该次打击后现存星球
的连通块个数。

Sample Input
8 13
0 1
1 6
6 5
5 0
0 6
1 2
2 3
3 4
4 5
7 1
7 2
7 6
3 6
5
1
6
3
5
7
Sample Output
1
1
1
2
3
3
 
第一次做这种题真的很难想,主要是不敢下手,在网上找了好多解析都是一言概之。还是觉得不要怕错,要自己按自己的思路写一下,发现其实还蛮简单的。
但感觉自己写的耗时有点多......
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<vector>
 6 #include<stack>
 7 #include<algorithm>
 8 using namespace std;
 9 #define N 400002
10 #define T(){printf("^^^ ");}
11 int bc[N], waitdel[N], vis[N], ans[N];;
12 vector<int>gra[N];
13 int find(int son)
14 {
15     int fa = son;
16     while(fa != bc[fa])
17     {
18         fa = bc[fa];
19     }
20     //
21     int temp = son,k;
22     while(fa != bc[temp])
23     {
24         k = bc[temp];
25         bc[temp] = fa;
26         temp = k;
27     }
28     return fa;
29 }
30  
31 int main()
32 {
33     int n,m,k,x,y;
34     cin>>n>>m;
35     for(int i=0; i<m; i++)
36     {
37         scanf("%d%d",&x,&y);
38         gra[x].push_back(y);
39         gra[y].push_back(x);
40     }
41     scanf("%d",&k);
42     memset(vis,0,sizeof(vis));
43     for(int i=0; i<k; i++)
44     {
45         scanf("%d",&waitdel[i]);
46         vis[waitdel[i]] = 1;
47     }
48     for(int i=0; i<n; i++) bc[i] = i;
49     int tot = n - k;
50     for(int i=0; i<n; i++)
51     {
52         if(!vis[i])
53         {
54             for(int j=0; j<gra[i].size(); j++)
55             {
56                 if(!vis[gra[i][j]])
57                 {
58                     int x = find(i);
59                     int y = find(gra[i][j]);
60                     if(x != y)
61                     {
62                         tot --;
63                         bc[y] = x;
64                     }
65                 }
66             }
67         }
68     }
69     int top = 0;
70     for(int i=k-1; i>=0; i--)
71     {
72         int k = waitdel[i];
73         ans[top ++] = tot;
74         tot ++;
75         for(int j=0; j<gra[k].size(); j++)
76         {
77             if(!vis[gra[k][j]])
78             {
79                 int x = find(k);
80                 int y = find(gra[k][j]);
81                 if(x != y)
82                 {
83                     tot --;
84                     bc[y] = x;
85                 }
86             }
87             vis[k] = 0;
88         }
89     }
90     ans[top++] = tot;
91     for(int i=top-1; i>=0; i--) printf("%d\n",ans[i]);
92 }

 

posted @ 2017-07-30 15:20  swallowblank  阅读(349)  评论(0编辑  收藏  举报