【题意】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; }