1015: [JSOI2008]星球大战starwar - BZOJ

Description

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

输入文件第一行包含两个整数,N (1 <= N <= 2M) 和M (1 <= M <= 200,000),分别表示星球的数目和以太隧道的数目。星球用0~N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0<=X<>Y
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 const
 2     maxn=400010;
 3     maxm=200010;
 4 var
 5     f,ans,s:array[0..maxn]of longint;
 6     flag:array[0..maxn]of boolean;
 7     first,last,next:array[0..maxn*2]of longint;
 8     n,m,q,num,tot:longint;
 9  
10 procedure insert(x,y:longint);
11 begin
12     inc(tot);
13     last[tot]:=y;
14     next[tot]:=first[x];
15     first[x]:=tot;
16 end;
17  
18 function find(x:longint):longint;
19 begin
20     if f[x]=x then exit(x);
21     f[x]:=find(f[x]);
22     exit(f[x]);
23 end;
24  
25 procedure init;
26 var
27     i,j,x,y:longint;
28 begin
29     read(n,m);
30     for i:=1 to n do
31       f[i]:=i;
32     for i:=1 to m do
33       begin
34         read(x,y);
35         insert(x+1,y+1);
36         insert(y+1,x+1);
37       end;
38     read(q);
39     for i:=1 to q do
40       begin
41         read(s[i]);
42         inc(s[i]);
43         if flag[s[i]]=false then flag[s[i]]:=true
44         else s[i]:=n+1;
45       end;
46     ans[q]:=n;
47     for i:=1 to n do
48       if flag[i]=false then
49       begin
50         j:=first[i];
51         while j<>0 do
52           begin
53             if flag[last[j]]=false then
54             begin
55               if find(i)<>find(last[j]) then
56               begin
57                 dec(ans[q]);
58                 f[f[i]]:=f[last[j]];
59               end;
60             end;
61             j:=next[j];
62           end;
63       end
64       else dec(ans[q]);
65 end;
66  
67 procedure work;
68 var
69     i,j:longint;
70 begin
71     for i:=q downto 1 do
72       if (flag[s[i]])and(s[i]<=n) then
73       begin
74         ans[i-1]:=ans[i]+1;
75         j:=first[s[i]];
76         while j<>0 do
77           begin
78             if flag[last[j]]=false then
79             if find(s[i])<>find(last[j]) then
80             begin
81               dec(ans[i-1]);
82               f[f[s[i]]]:=f[last[j]];
83             end;
84             j:=next[j];
85           end;
86         flag[s[i]]:=false;
87       end
88       else ans[i-1]:=ans[i];
89     for i:=0 to q do
90       writeln(ans[i]);
91 end;
92  
93 begin
94     init;
95     work;
96 end.
View Code

 

posted @ 2014-03-21 09:45  Randolph87  阅读(335)  评论(0编辑  收藏  举报