您的位置:首页 > 其它

HDU 5652 India and China Origins

2016-04-02 12:21 465 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5652

中文题面:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=681&pid=1002

题意:两个国家之间有一个地图,地图上有一些山峰,即障碍。一开始两个国家是相通的,现在在地图上依次出现Q座山峰,一年出现一座。问两国最早不联通是在几年后。



思路:可以用并查集来做,地图上有n*m个点,那么两个国家的编号可以设为0和m*n+1,将地图上的每个点都与四个方向判一下是否可行,就合并。上下两行边界分别去和0和n*m+1合并。将所有的操作倒着处理,假设一开始Q座山峰都是出现的,然后每次减少一座山峰,就把这个位置和地图上联通起来,判断0和n*m+1这两个点的连通性。



#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0};

const int maxn = 500;
int T,n,m;

char a[maxn+10][maxn+10];
int father[maxn*maxn+10];
int qx[maxn*maxn+10],qy[maxn*maxn+10];
int Q;

int getpos(int x,int y)
{
return (x-1)*m + y;
}

int getfather(int x)
{
if ( father[x] == x ) return x;
return father[x] = getfather( father[x] );
}

void unio(int x,int y)
{
int fa = getfather(x);
int fb = getfather(y);
if ( fa != fb )
{
father[fa] = fb;
}
}

void init()
{
rep(i,0,m*n+1) father[i] = i;
rep(i,1,n)
{
getchar();
rep(j,1,m) a[i][j] = getchar();
}
scanf("%d",&Q);
rep(i,1,Q)
{
scanf("%d%d",&qx[i],&qy[i]);
qx[i]++;
qy[i]++;
a[qx[i]][qy[i]] = '1'; //先将所有的山峰都放上
}
rep(i,1,m)
{
if ( a[1][i] ) unio( getpos(1,i) , 0 ); //上下边界两行和国家联通
if ( a
[i] ) unio( getpos(n,i) , n*m+1 );
}
int tx,ty;
rep(i,1,n)  //将整个地图可行的地方都联通
rep(j,1,m)
if ( a[i][j] == '0' )
rep(k,0,3)
{
tx = i + dx[k];
ty = j + dy[k];
if ( tx >=1 && tx <= n && ty>=1 && ty <= m && a[tx][ty] == '0' ) unio( getpos(i,j) , getpos(tx,ty) );
}
}

int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
int st = 0;
int ed = n*m + 1;
if ( getfather(st) == getfather(ed) ) //一开始就是连通的
{
puts("-1");
continue;
}
int tx,ty;
Rrep(i,Q,1)
{
a[ qx[i] ][ qy[i] ] = '0';//每次去掉一个山峰,再判断图的连通性
rep(k,0,3)
{
tx = qx[i] + dx[k];
ty = qy[i] + dy[k];
if ( tx >=1 && tx <= n && ty>=1 && ty <= m && a[tx][ty] == '0' ) unio( getpos(qx[i],qy[i]) , getpos(tx,ty) );
}
if ( getfather(st) == getfather(ed) )
{
printf("%d\n",i);
break;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: