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

 

你可能感兴趣的:(2008)