hdu5652 India and China Origins(并查集)

来源:互联网 发布:c excel重复数据删除 编辑:程序博客网 时间:2024/05/21 20:26

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5652

题目大意:

在n*m的矩阵里面,放值为1的山峰。当山峰连起来能够封锁整个m列的时候,问最早是什么时候。

范围:

n,m<=500,Q<=n*m。

思路:

可以用并查集存下每个点能向左延伸的距离和向右延伸的距离。当有一个点为1的时候,看他8个方向是否有为1的山峰,如果有就将他们并入同一个集合,然后更新他们的最左和最右。当能够封锁的时候,就是答案。

代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;int n,m,x[250500],y[250500];struct node{    int l,r,num;}p[5500005];char  s[505][505];void init(){    int i,j;    for(i=0;i<=505;i++)    for(j=0;j<=505;j++)    {        p[i*1000+j].l=j;        p[i*1000+j].r=j;        p[i*1000+j].num=1000*i+j;  //初始化将点化为数。    }    return ;}int findroot(int x){    int r=x;    while(r!=p[r].num)    r=p[r].num;    int i=x,j;    while(i!=r)    {        j=p[i].num;        p[i].num=r;        i=j;    }    return r;}int join(int x,int y){    int fx,fy;    fx=findroot(x);    fy=findroot(y);    if(fx<fy){        p[fy].num=fx;        int mi,ma;        mi=min(min(p[y].l,p[fx].l),min(p[x].l,p[fy].l));        ma=max(max(p[y].r,p[fx].r),max(p[x].r,p[fy].r));        p[fy].l=p[x].l=p[y].l=p[fx].l=mi;        p[fy].r=p[x].r=p[y].r=p[fx].r=ma;        return fx;    }    else {    p[fx].num=fy;    int mi,ma;        mi=min(min(p[y].l,p[fx].l),min(p[x].l,p[fy].l));        ma=max(max(p[y].r,p[fx].r),max(p[x].r,p[fy].r));        p[fy].l=p[x].l=p[y].l=p[fx].l=mi;        p[fy].r=p[x].r=p[y].r=p[fx].r=ma;    return fy;    }}void judge(int x,int y){    int a,b;    if(s[x][y+1]==1&&y+1<=m){        a=x*1000+y;        b=x*1000+y+1;        int mi=join(a,b);    }    if(s[x+1][y+1]==1&&x+1<=n&&y+1<=m){        a=x*1000+y;        b=(x+1)*1000+y+1;        int mi=join(a,b);    }    if(s[x+1][y]==1&&x+1<=n){        a=x*1000+y;        b=(x+1)*1000+y;        int mi=join(a,b);    }    if(s[x+1][y-1]==1&&x+1<=n&&y-1>0)    {         a=x*1000+y;        b=(x+1)*1000+y-1;        int mi=join(a,b);    }    if(s[x][y-1]==1&&y-1>0)    {         a=x*1000+y;        b=(x)*1000+y-1;        int mi=join(a,b);    }    if(s[x-1][y-1]==1&&x-1>0&&y-1>0)    {         a=x*1000+y;        b=(x-1)*1000+y-1;        int mi=join(a,b);    }     if(s[x-1][y]==1&&x-1>0){          a=x*1000+y;        b=(x-1)*1000+y;        int mi=join(a,b);     }     if(s[x-1][y+1]==1&&x-1>0&&y+1<=m)     {         a=x*1000+y;         b=(x-1)*1000+y+1;         int mi=join(a,b);     }}int main(){    int T,i,j,k,Q;        scanf("%d",&T);    while(T--)    {        memset(x,0,sizeof(x));        memset(y,0,sizeof(y));        for(i=0;i<505;i++)        for(j=0;j<505;j++)        s[i][j]=0;        init();        scanf("%d%d",&n,&m);        for(i=1;i<=n;i++)        for(j=1;j<=m;j++)        {            cin>>s[i][j];            s[i][j]-='0';        }        int ff=0;        for(i=1;i<=n;i++)        for(j=1;j<=m;j++)        {            if(s[i][j]==1){                judge(i,j);                int aa=i*1000+j;                aa=findroot(aa);                if(p[aa].r-p[aa].l==m-1){                    ff=1;                    break;                }            }        }        scanf("%d",&Q);        for(i=1;i<=Q;i++)        scanf("%d%d",&x[i],&y[i]);        if(ff){            printf("0\n");            continue;        }        int f=0;        for(i=1;i<=Q;i++)        {            s[x[i]+1][y[i]+1]=1;            judge(x[i]+1,y[i]+1);            int fx;            fx=findroot((x[i]+1)*1000+y[i]+1);            if(p[fx].r-p[fx].l==m-1){                printf("%d\n",i);                f=1;                break;            }        }        if(f==0)printf("-1\n");    }}/*3 301000001050 01 00 21 12 0*/


0 0
原创粉丝点击