题目
Description
从前有一个Baby。
从前还有一个网格图。
Baby 喜欢爆炸。
Baby 偶尔会炸掉网格图中的一条边(u, v)。之后他会尝试从u 走到v。
如果他成功地从u 走到v,他会很高兴;否则他会找人打架。
从第二次爆炸开始,根据Baby 此时心情的不同,Baby 会炸掉不同的边。
你被要求编写一个程序,对于每次爆炸,给出此时Baby 是否还能从u 到v。
Input
第一行,一个整数R,代表网格图是R*R 的。
第二行,一个整数N,代表操作数。
第三行,四个整数x1,y1,x2,y2,描述了第一次爆炸的边。
以下N-1 行,每行四个整数x1,y1,x2,y2,x1’,y1’,x2’,y2’,分别描述Baby 高兴时炸的边和
想找人打架时炸的边。
Output
输出N 行,如果本次爆炸后Baby 高兴,输出一行“HAHA”,否则输出一行“DAJIA”
Sample Input
2
2
1 1 1 2
1 1 2 1 1 2 2 2
Sample Output
HAHA
DAJIA
Data Constraint
对于40%的数据,R≤50。
对于100%的数据,1≤R≤500,1≤N≤2R^2-2R。
对于100%的数据,1≤x1,x2,x1’,x2’≤R,1≤y1,y2,y1’,y2’≤R。
对于所有对边的描述,要么x1=x2 且|y1-y2|=1,要么y1=y2 且|x1-x2|=1。
保证所有边至多被删除一次。
均匀地,对于50%的数据,x1=x1’,y1=y1’,x2=x2’,y2=y2’。
请注意输入输出规模较大。
题解
首先发现这一题是动态的删边,然后问你这一条将要被删的边是不是桥
可以发现这道题设置了强制在线
那么似乎没有什么算法可以处理这个问题,应该是一道神奇的思路题
考虑把每一个被4条边圈起来的一个空间成为“域”
那么我们每一次删边就相当于把两个域连了起来
如果这两个域本来就连了起来,那么这条边就是一个桥
为什么呢?
考虑到两个域在这之前已经连了起来,那么它们之间必定有一条类似于“半圆”的道路,而这条道路上的边都已经被删了,而且这个东西把两个点包了起来
也就是说如果不走将要删的边而是要走其他路径一定会装上那个“半圆”
所以我们并查集处理一下每一个域的连接情况
贴代码
var
fa:array[0..200005]of longint;
a:array[0..200005]of longint;
x,y,x1,y1:longint;
i,j,k,l,r,n,m:longint;
bz:boolean;
function getfather(x:longint):longint;
begin
if fa[x]=x then exit(x) else
fa[x]:=getfather(fa[x]);
exit(fa[x]);
end;
procedure make;
var
i,j,k,yu1,yu2,fa1,fa2:longint;
begin
if x=x1 then
begin
if y>y1 then
begin
k:=y;
y:=y1;
y1:=k;
end;
yu1:=(x-1)*(r-1)+y;
yu2:=yu1-r+1;
if yu2<0 then yu2:=0;
end else
begin
if x>x1 then
begin
k:=x;
x:=x1;
x1:=k;
end;
yu1:=(x-1)*(r-1)+y;
yu2:=yu1-1;
if yu1 mod (r-1)=1 then
begin
if y=1 then yu2:=0 else yu1:=0;
end;
if yu2<0 then yu2:=0;
end;
if yu1>(r-1)*(r-1) then yu1:=0;
fa1:=getfather(yu1);
fa2:=getfather(yu2);
if fa1<>fa2 then
begin
bz:=false;
writeln('HAHA');
fa[fa1]:=fa2;
end else
begin
bz:=true;
writeln('DAJIA');
end;
end;
begin
//assign(input,'t2.in'); reset(input);
readln(r);
readln(n);
readln(x,y,x1,y1);
for i:=0 to (r-1)*(r-1) do fa[i]:=i;
make;
for i:=1 to n-1 do
begin
if bz=false then readln(x,y,x1,y1,l,l,l,l)
else readln(x,y,x1,y1,x,y,x1,y1);
make;
end;
//close(input);
end.