【题意】bc中文题,题意自己看啦!!!
【解题思路】 这是一个连通性的问题。你会发现如果将所有操作逆序来看的话就很容易用并查集来处理了。首先把所有的山峰都加到图中,然后逆序处理每个操作:对某次操作,在图中删除该位置的山峰,然后判断两个点是否联通,一旦联通就得到了结果。这里需要对China和India分别新建一个对应的节点。
【AC代码】
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 510;
char s[maxn][maxn];
int fa[maxn*maxn];
int x[maxn*maxn],y[maxn*maxn];
int dir[4][2]= {{0,1},{0,-1},{1,0},{-1,0}};
int S,T,n,m,q;
int Code(int x,int y)
{
return x*m+y;
}
int Find(int x)
{
if(fa[x]==x)return fa[x];
else
return fa[x]=Find(fa[x]);
}
void union_set(int x,int y)
{
int fx=Find(x),fy=Find(y);
if(fx!=fy)
{
fa[fx]=fy;
}
}
bool check(int x,int y)
{
if(x>=0&&x<n&&y>=0&&y<m)return true;
return false;
}
void Init()
{
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<n; i++)scanf("%s",s[i]);
for(int i=0; i<=n*m+1; i++)fa[i]=i;
S = n*m,T=n*m+1;
scanf("%d",&q);
for(int i=1; i<=q; i++)
{
scanf("%d%d",&x[i],&y[i]);
s[x[i]][y[i]]='1';
}
Init();
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(s[i][j]=='0')
{
for(int k=0; k<4; k++)
{
int dx = i+dir[k][0];
int dy = j+dir[k][1];
if(!check(dx,dy)||s[dx][dy]=='1')continue;
union_set(Code(dx,dy),Code(i,j));
}
if(i==0) union_set(S,Code(i,j));
if(i==n-1) union_set(T,Code(i,j));
}
}
}
if(Find(S)==Find(T))
{
puts("-1");
continue;
}
for(int i=q; i>=1; i--)
{
s[x[i]][y[i]]='0';
for(int k=0; k<4; k++)
{
int dx = x[i]+dir[k][0];
int dy = y[i]+dir[k][1];
if(!check(dx,dy)||s[dx][dy]=='1')continue;
union_set(Code(x[i],y[i]),Code(dx,dy));
}
if(x[i]==0) union_set(S,Code(x[i],y[i]));
if(x[i]==n-1) union_set(T,Code(x[i],y[i]));
if(Find(S)==Find(T))
{
printf("%d\n",i);
break;
}
}
if(Find(S)!=Find(T))
{
puts("0");
continue;
}
}
return 0;
}