东东的轰炸游戏(bomb.pas/.c/.cpp)
题目描述 东东 和东东爸在玩一个即时战略游戏,东东要轰炸东东爸 的基地,其中东东爸的基地 由n个建筑物和m条道路联通。东东每次轰炸只能炸毁东东爸 基地中的一条道路。
假设有一条道路【x,y】,如果被东东炸毁后,建筑物x和y不联通,那么东东就会非 常的高兴,下次轰炸就会选择炸毁下一条道路;否则如果x 和y联通,那么东东就非常的 生气,下次轰炸会改变原来的主意,选择炸毁另外一条道路。
输入格式 第一行两个整数n,m。表示东东爸 的基地有n个建筑物,m条道路。
接下来m 行中,每i行两个整数xi,yi,表示第i号边连接建筑物xi和yi。
接下来一行一个正整数k。表示东东顺序的k次轰炸。
接下来k行中,第一行一个正整数,表示第一次轰炸的道路的编号。之后的k-1行每行 两个正整数a,b,其中如果上次轰炸东东高兴,这次选择第a号边,否则选择第b号边。
数据保证:图中没有自环、重边;每条道路最多会被轰炸一次。
输出格式 输出k行,每行对应一个结果。 如果东东高兴那么输出“:)”,否则输出“:(”。(不含引号)
样例输入
3 3
1 2
2 3
3 1
2
1
2 3
样例输出
:(
:)
数据范围与约定
1到5号测试点:n<=1000,m<=10000,k<=1000,不保证a=b。
6到10号测试点:n<=10000,m<=100000,k<=m,并且保证a=b。
这是一道分成两半的题。。 很容易看出来如果数据很水可以直接dfs爆搜,幸运的是前五个点应该设置的都是暴力点,使用邻接表记录路径,每次删边之后dfs判断能否走到即可。 至于后五个点,因为a=b所以不用考虑路径问题 ,即不需要考虑上一次轰炸的高兴与否。所以先将所有的路径存入数组,把所有不需要轰炸的路径两侧的点合并,再逆着轰炸的顺序,先判断两点是否在一个集合中,用boolean数组记录,然后合并。最后按照顺序输出结果即可
program mys;
var a,i,j,k,m,n,l,r,xx,yy:longint;
p:array[0..1000,0..7000]of longint;
b,e:array[0..200000]of boolean;
bb:array[0..150000]of boolean;
x,y:array[0..200000]of longint;
f,g:array[0..200000]of longint;
procedure dele(xx,yy:longint);
var i:longint;
begin
for i:=1 to p[xx,0] do
if p[xx,i]=yy then
begin
p[xx,i]:=0;
break;
end;
end;
procedure dfs(x:longint);
var ii:longint;
begin
bb[x]:=true;
for ii:=1 to p[x,0] do
begin
if p[x,ii]=yy then
begin
b[i]:=true;
break;
end;
if (p[x,ii]<>0)and(bb[p[x,ii]]=false) then
dfs(p[x,ii]);
if b[i] then break;
end;
end;
function find(x:longint):longint;
begin
if f[x]<>x then f[x]:=find(f[x]);
exit(f[x]);
end;
procedure union(x,y:longint);
begin
x:=find(x);
y:=find(y);
if x<>y then f[x]:=y;
end;
begin
assign(input,'bomb.in'); reset(input);
assign(output,'bomb.out'); rewrite(output);
readln(n,m);
if n<=1000 then
begin
fillchar(b,sizeof(b),false);
for i:=1 to n do
p[i,0]:=0;
for i:=1 to m do
begin
readln(x[i],y[i]);
inc(p[x[i],0]);
p[x[i],p[x[i],0]]:=y[i];
inc(p[y[i],0]);
p[y[i],p[y[i],0]]:=x[i];
end;
readln(k);
readln(a);
i:=1;
xx:=x[a]; yy:=y[a];
dele(xx,yy);
dele(yy,xx);
fillchar(bb,sizeof(bb),false);
dfs(xx);
if b[i] then writeln(':(')
else writeln(':)');
for i:=2 to k do
begin
read(l,r);
if b[i-1]=true then
begin
xx:=x[r]; yy:=y[r];
end
else
begin
xx:=x[l]; yy:=y[l];
end;
dele(xx,yy);
dele(yy,xx);
fillchar(bb,sizeof(bb),false);
dfs(xx);
if b[i] then writeln(':(')
else writeln(':)')
end;
end
else
begin
fillchar(b,sizeof(b),true);
for i:=1 to m do
readln(x[i],y[i]);
for i:=1 to n do
f[i]:=i;
readln(k);
readln(g[1]);
b[g[1]]:=false;
for i:=2 to k do
begin
readln(g[i],g[i]);
b[g[i]]:=false;
end;
for i:=1 to m do
if b[i] then
union(x[i],y[i]);
for i:=k downto 1 do
begin
if find(x[g[i]])=find(y[g[i]]) then
e[i]:=false
else e[i]:=true;
union(x[g[i]],y[g[i]]);
end;
for i:=1 to k do
if e[i] then
writeln(':)')
else writeln(':(');
end;
close(input);
close(output);
end.