1015: [JSOI2008]星球大战starwar

1015: [JSOI2008]星球大战starwar

Time Limit: 3 Sec  Memory Limit: 162 MB
Submit: 3001  Solved: 1321
[Submit][Status]

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

HINT

Source

题解:正如JSZKC神犇所言——既然并查集不能合并,那么倒着插入不就行了?于是乎我这么做了一下,结果是70分,TLE。。。然后我只好找网上的标程,结果发现了人家在并查集里面有个异常强悍的优化(具体见程序里面的getfat函数),然后就擦着边AC了。。。具体做法是——先把所有边里面没有涉及到被删除点的全部合并,然后按照删点顺序倒着来合并,这一路每次要记录下连通块数量。。。(注意:最后输出时要-i+1,因为假如举个例子,所有的星球在最后的数据中都被干掉了的话,那么假如单纯是连通块的话,应该有N个才是,可是事实上一个星球都没了。。。)

 1 type point=^node;
 2      node=record
 3                 g:longint;
 4                 next:point;
 5      end;
 6 var
 7    i,j,k,l,m,n,t:longint;
 8    a:array[0..400000] of point;
 9    c,b,d,e:array[0..400000] of longint;
10    p:point;
11 function getfat(x:longint):longint;inline;
12          begin
13               if x<>c[x] then
14                  begin
15                       c[x]:=getfat(c[x]);  //orz强悍的优化
16                  end;
17               exit(c[x]);
18          end;
19 function tog(x,y:longint):boolean;inline;
20          begin
21               exit(getfat(x)=getfat(y));
22          end;
23 procedure merge(x,y:longint);inline;
24           begin
25                c[getfat(x)]:=getfat(y);
26           end;
27 procedure add(x,y:longint);inline;
28           var p:point;
29           begin
30                new(p);
31                p^.g:=y;
32                p^.next:=a[x];
33                a[x]:=p;
34           end;
35 begin
36      readln(n,m);
37      for i:=1 to n do
38          begin
39               c[i]:=i;
40               a[i]:=nil;
41          end;
42      for i:=1 to m do
43          begin
44               readln(j,k);
45               add(j+1,k+1);add(k+1,j+1);
46          end;
47      fillchar(b,sizeof(b),0);
48      readln(t);
49      for i:=1 to t do
50          begin
51               readln(d[i]);
52               d[i]:=d[i]+1;
53               b[d[i]]:=1;
54          end;
55      l:=n;
56      for i:=1 to n do
57          begin
58               if b[i]=0 then
59                  begin
60                       p:=a[i];
61                       while p<>nil do
62                             begin
63                                  if b[p^.g]=0 then
64                                     begin
65                                          if not(tog(i,p^.g)) then
66                                             begin
67                                                  dec(l);merge(i,p^.g);
68                                             end;
69                                     end;
70                                  p:=p^.next;
71                             end;
72                  end;
73          end;
74      e[t+1]:=l;
75      for i:=t downto 1 do
76          begin
77               b[d[i]]:=0;
78               p:=a[d[i]];
79               while p<>nil do
80                     begin
81                          if b[p^.g]=0 then
82                             begin
83                                  if not(tog(d[i],p^.g)) then
84                                     begin
85                                          merge(d[i],p^.g);
86                                          dec(l);
87                                     end;
88                             end;
89                          p:=p^.next;
90                     end;
91               e[i]:=l;
92          end;
93      for i:=1 to t+1 do writeln(e[i]-i+1);
94 end.     
时间: 2024-08-04 20:11:58

1015: [JSOI2008]星球大战starwar的相关文章

bzoj1015:1015: [JSOI2008]星球大战starwar

应该是全部读入之后再添加边用并查集就可以了. yyl用空间换时间.u[]v[]等将边预存起来. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--)

BZOJ 1015: [JSOI2008]星球大战starwar 并查集

1015: [JSOI2008]星球大战starwar Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重新造出了他的超级武器.凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球.由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来.现在,反抗军首领交给你一个任务:给出原

【BZOJ】1015: [JSOI2008]星球大战starwar(并查集)

http://www.lydsy.com/JudgeOnline/problem.php?id=1015 看了题解的囧T_T,一开始以为是求割点,但是想到割点不能统计.... 这题用并查集,思想很巧妙. 我们按照逆序建图,也就是从最后一个毁了的星球之后建图.然后从后往前走. 那么怎么统计联通块呢?很简单,我们开个数组记录没有被破坏的星球,然后每一次都将一个星球拿去访问他连接的其他点,看他们是否在一个联通块,如果不是,那么就将连接的那个点加入自己的联通块. #include <cstdio> #

BZOJ 1015 JSOI2008 星球大战 starwar 并检查集合

标题效果:给定一个无向图.联通谋求块的数目,以及k一个点的破坏后每次:联通,块的数目 侧面和摧毁的地步全记录,我们可以做相反的. 需要注意的是该点不能算作破坏联通块 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 400400 using namespace std; struct abcd{ int to,next; }table[M];

BZOJ 1015 JSOI2008 星球大战 starwar 并查集

题目大意:给定一个无向图,求联通块个数,以及k次每次摧毁一个点后的:联通块个数 将边和摧毁的点全记录下来,反着做即可. 注意被摧毁的点不能算作联通块 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 400400 using namespace std; struct abcd{ int to,next; }table[M]; int hea

bzoj 1015: [JSOI2008]星球大战starwar

1 #include<cstdio> 2 #include<iostream> 3 #define M 2000000 4 int cnt,fa[M],n,m,ans[M],k,f[M],a[M],head[M],next[2*M],u[2*M]; 5 int zhao(int a1) 6 { 7 if(a1==fa[a1]) 8 return a1; 9 fa[a1]=zhao(fa[a1]); 10 return fa[a1]; 11 } 12 void jia(int a1,

BZOJ 1015: [JSOI2008]星球大战starwar【并查集】

题目可以表述成:给定一个无向图G,每次删除它的一个点和与点相关的边集,每次询问该操作后图G的连通度(连通分量的个数).和上一题一样都是考察逆向思维,虽然删除点的做法不会,但是每次加点后询问连通度却是并查集的经典用法,所以答案可以逆过来推,具体做的时候每次加入一个点,将所有和这个点有边相连的点集合并,然后输出当前有多少个集合.细节部分需要注意的是由于点的数量十分庞大,邻接表是十分有必要的 #include<iostream> #include<cstdio> #include <

【BZOJ 1015】[JSOI2008]星球大战starwar

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3685  Solved: 1641[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重

BZOJ1015[JSOI2008]星球大战starwar[并查集]

1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5253  Solved: 2395[Submit][Status][Discuss] Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或间接地连接. 但好景不长,很快帝国又重