[bzoj1005] [JSOI2008]星球大战starwar

想了半天决定第一篇就发一道水题的题解吧……这道题以前就看了但是神奇的第一次没有写对,然后今天写代码+调试,额……二十分钟……

题目懒得贴了,直接戳这里

题目大意就是给你一个图(毫无疑问稀疏图),然后每一次抹去其中一个节点,然后求这时的连通块个数。

第一次看这题的时候在学tarjan,第一反应就是每次把点去掉跑tarjan,然后看了下数据范围就放弃了【其实也能过几个点对不对233】

然后就想到用并查集,把所有的操作全部用一个数组存下来,然后倒着合并。

首先将所有要消除的点全部抹去,用并查集求出当前连通块的个数,然后根据给出的顺序,每一次“激活”一个点,然后和它所连的激活的点合并,最后倒着输出就可以了。

关于合并统计连通块个数:

①将所有要消除的点抹去后,ans:=n-k,然后在当前图中开始合并,即如果发现有两个点有边相连且不在同一个连通块中,那么合并两个连通块且ans:=ans-1。最后统计出的就是将所有指定的星球全部毁灭后的连通块个数

②添加点时注意ans:=ans+1,因为当添加了一个点就相当于又添加了一个连通块.然后合并,统计方法和上面一样,如果不在一个连通块中则ans:=ans-1.此时统计出的是在当前所添加的星球未被毁灭之前的连通块个数

还有要注意的一点就是数据范围比较大,邻接矩阵不够存要用邻接表。另外为了时间更快用的并查集的路径压缩(不会直接度娘)

其他的就什么好说的了,我属于代码写的比较丑的类型也只写了八十多行,下面贴代码

 1 program j01;
 2 var x,y,n,m,i,j,k,t,ans:longint;
 3     f:array[0..500000]of longint;
 4     a,c:array[1..500000]of longint;
 5     b:array[0..500000]of boolean;
 6     q,next,head:array[0..500000]of longint;
 7 function gg(i:longint):longint;//并查集查找部分,这里为了时间快用了压缩路径
 8 var x:longint;
 9 begin
10   if f[i]=i then exit(i);
11   x:=gg(f[i]);
12   f[i]:=x;
13   exit(x);
14 end;
15 procedure merge(i,j:longint);
16 var x,y:longint;
17 begin
18   x:=gg(i);
19   y:=gg(j);
20   f[x]:=y;
21 end;
22 procedure add(a,b:longint);//邻接表
23 begin
24   inc(t);
25   q[t]:=b;
26   next[t]:=head[a];
27   head[a]:=t;
28 end;
29 begin
30   readln(n,m);
31   fillchar(head,sizeof(head),0);
32   t:=0;
33   for i:=1 to m do
34   begin
35     readln(x,y);
36     add(x,y);
37     add(y,x);
38   end;
39   readln(k);
40   fillchar(b,sizeof(b),true);
41   for i:=1 to k do
42   begin
43     readln(a[i]);
44     b[a[i]]:=false;
45   end;
46   ans:=n-k;
47   for i:=0 to n-1 do f[i]:=i;
48   for i:=0 to n-1 do
49   begin
50     j:=head[i];
51     if b[i] then
52       while j<>0 do
53       begin
54         if b[q[j]] then
55           if gg(i)<>gg(q[j]) then
56           begin
57             dec(ans);
58             merge(i,q[j]);
59           end;
60         j:=next[j];
61       end;
62   end;//统计最后连通块个数
63   for i:=k downto 1 do
64   begin
65     c[i]:=ans;//这里的ans记录的是i+1次毁灭星球之前连通块个数,即i次毁灭星球是后的连通块个数
66     b[a[i]]:=true;
67     ans:=ans+1;
68     j:=head[a[i]];
69     while j<>0 do
70     begin
71       if b[q[j]] then
72         if gg(a[i])<>gg(q[j]) then
73         begin
74           dec(ans);
75           merge(a[i],q[j]);
76         end;
77       j:=next[j];
78     end;
79   end;//统计每一次毁灭前连通块个数
80   writeln(ans);
81   for i:=1 to k do writeln(c[i]);
82 end.
时间: 2024-10-17 14:17:38

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

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

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

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

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

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

1015: [JSOI2008]星球大战starwar

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

bzoj1015 [JSOI2008]星球大战starwar

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

[JSOI2008]星球大战starwar

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

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

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

【BZOJ】[JSOI2008]星球大战starwar

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