倒序操作用并查集判断是否连通,新技能get√(其实以前就会了
这题细节很多。。。搞得整个程序都是调试输出,几度看不下去想要重写
并查集到现在大概掌握了两个基本用途:判断是否连通 / 路径压缩(上一篇blog)UPD:判断某个区间是否被覆盖
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int dx[]={,,,-,},dy[]={,,,,-},maxn=;
int n,m,china,india,T,q,fa[maxn],x[maxn],y[maxn];
bool v[][],map[][],map2[][];
char s[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
int bh(int x,int y)
{
if(x==)return n*m+;
if(x==n+)return n*m+;
return (x-)*m+y;
}
void dfs(int x,int y)
{
v[x][y]=;
for(int i=;i<=;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(nx>n||nx<||ny>m||ny<)continue;
if((!v[nx][ny])&&(!map[nx][ny])&&(!map2[nx][ny]))
fa[gf(bh(nx,ny))]=gf(bh(x,y)),dfs(nx,ny);
}
}
int main()
{
read(T);
while(T--)
{
memset(v,,sizeof(v));
memset(map,,sizeof(map));
memset(map2,,sizeof(map2));
read(n);read(m);china=n*m+;india=n*m+;
for(int i=;i<=n;i++)
{
scanf("%s",s);
for(int j=;j<m;j++)
map[i][j+]=s[j]-'';
}
read(q);
for(int i=;i<=q;i++)
{
read(x[i]);read(y[i]);
x[i]++;y[i]++;
map2[x[i]][y[i]]=;
}
for(int i=;i<=n*m+;i++)fa[i]=i;
for(int i=;i<=m;i++)
if((!map[][i])&&(!v[][i])&&(!map2[][i]))fa[gf(bh(,i))]=gf(china),dfs(,i);
for(int i=;i<=m;i++)
if((!map[n][i])&&(!v[n][i])&&(!map2[n][i]))fa[gf(bh(n,i))]=gf(india),dfs(n,i);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)
if((!map[i][j])&&(!v[i][j])&&(!map2[i][j]))dfs(i,j);
if(gf(china)==gf(india))printf("-1\n");
else
for(int i=q;i;i--)
{
map2[x[i]][y[i]]=;
for(int j=;j<=;j++)
if((!map[x[i]+dx[j]][y[i]+dy[j]])&&(!map2[x[i]+dx[j]][y[i]+dy[j]]))
fa[gf(bh(x[i]+dx[j],y[i]+dy[j]))]=gf(bh(x[i],y[i]));
if(gf(china)==gf(india))
{
printf("%d\n",i);
break;
}
}
}
return ;
}