题目大意:
机房的位置一共有n 行m 列,一开始每个位置都有一滴学水,TerryHu 决定在每一个时刻选择
一滴学水进行蒸发,直到机房里不再存在学水。
TerryHu 想知道在每个时刻之后,机房里剩下的学水构成了几个联通块。
对于60% 的数据:n,m<= 50;
对于100% 的数据:n,m<= 1000。
题解:
邻接表+并查集:
这题我们直接暴力的去做,很明显只能过60分的点
即暴力的枚举,时间复杂度:O((NM)^2)
我们用邻接表去记录不同大小的数的位置
然后我们逆向思维地用并查集去做
我们从后往前即学水大到小依次加入,这样我们就可以保证每次得到的ans[x]就是第x时刻的联通块数
对于每次加入的[x,y]
如果周边没有学水,那么ans+1
如果周边有学水,而且有y滴,那么很明显会想到ans-y+1,不过有y滴并不代表一定有y个联通块,因为y滴学水之间可能有相通的,这时候用并查集去处理即可。
代码:
const
dx:array [1..4] of longint=(1,-1,0,0);
dy:array [1..4] of longint=(0,0,-1,1);
var
a:array [0..1001,0..1001] of longint;
f:array [0..1000001] of longint;
list:array [0..1000001,1..2] of longint;
fd,next:array [0..1001,0..1001,1..2] of longint;
mind:array [1..4] of boolean;
xx,yy,ans,x,y,i,j,k,n,m:longint;
procedure find(cx,cy:longint);
begin
if (fd[cx,cy,1]=cx) and (fd[cx,cy,2]=cy) then
begin
xx:=cx;
yy:=cy;
exit;
end;
find(fd[cx,cy,1],fd[cx,cy,2]);
fd[cx,cy,1]:=xx;
fd[cx,cy,2]:=yy;
end;
procedure insert(cx,cy:longint);
var
i,j,k,d,x1,y1,x2,y2:longint;
begin
k:=0;
d:=0;
fillchar(mind,sizeof(mind),false);
for i:=1 to 4 do
if a[cx+dx[i],cy+dy[i]]=1 then
begin
inc(k);
if not(mind[i]) then
begin
find(cx+dx[i],cy+dy[i]);
x1:=xx; y1:=yy;
for j:=1 to 4 do
if (i<>j) and (not(mind[j])) and (a[cx+dx[j],cy+dy[j]]=1) then
begin
find(cx+dx[j],cy+dy[j]);
x2:=xx; y2:=yy;
if (x1=x2) and (y1=y2) then
begin
mind[i]:=true;
mind[j]:=true;
end;
end;
inc(d);
end;
end;
for i:=1 to 4 do
if a[cx+dx[i],cy+dy[i]]=1 then
begin
find(cx+dx[i],cy+dy[i]);
fd[xx,yy,1]:=cx;
fd[xx,yy,2]:=cy;
end;
if d=0 then
begin
ans:=ans-k+1;
exit;
end;
ans:=ans-d+1;
end;
begin
assign(input,'evaporate.in'); reset(input);
assign(output,'evaporate.out'); rewrite(output);
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(k);
next[i,j,1]:=list[k,1];
next[i,j,2]:=list[k,2];
list[k,1]:=i;
list[k,2]:=j;
end;
readln;
end;
ans:=0;
for k:=n*m downto 1 do
begin
f[k]:=ans;
x:=list[k,1]; y:=list[k,2];
while x>0 do
begin
a[x,y]:=1;
fd[x,y,1]:=x;
fd[x,y,2]:=y;
i:=x; j:=y;
insert(x,y);
x:=next[i,j,1];
y:=next[i,j,2];
end;
end;
for i:=1 to n*m do writeln(f[i]);
close(input); close(output);
end.