zoukankan      html  css  js  c++  java
  • hdu 5652

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5652

    题目意思:中国和印度之间本来有路连通,但有山在一时刻凸起。把路看成n*m的方格,值为为1则有山,0则没有。

    有q个询问,每个询问凸起一个坐标的山。问什么时候路不相通了。

    思路:并查集,把相邻的点当成一个集合,更新每个集合的左右边界(即这个集合内最左的没左边界,最右的为右边界),再

    合并八个方向的集合。直到路封死。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=505;
    struct node{
        int l,r;
    }a[maxn*maxn];//记录每个集合的左右边界 
    int fa[maxn*maxn];//每个点的父结点 
    int map[maxn][maxn];
    int n,m,q,ans;
    bool flag;//标记是否路完全封死 
    int dx[]={-1,-1,-1,0,0,1,1,1};
    int dy[]={-1,0,1,-1,1,-1,0,1};
    
    int find(int x)//寻找根结点 
    {
        if(x==fa[x])
            return x;
        else
            return fa[x]=find(fa[x]);
    }
    
    void unionn(int x,int y)//连接两个集合,或者说是树 
    {
        x=find(x),y=find(y);
        if(x!=y)
            fa[y]=x;
    }
    
    void solve(int i,int j)//判断询问 
    {
        for(int k=0;k<8;k++)//八个方向是否有集合可以合并 
        {
            int xx=i+dx[k];
            int yy=j+dy[k];
            if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&map[xx][yy]==1&&find((i-1)*m+j)!=find((xx-1)*m+yy))
            {
                //和下面处理一样 
                a[find((i-1)*m+j)].l=a[find((xx-1)*m+yy)].l=min(a[find((i-1)*m+j)].l,a[find((xx-1)*m+yy)].l);
                a[find((i-1)*m+j)].r=a[find((xx-1)*m+yy)].r=max(a[find((i-1)*m+j)].r,a[find((xx-1)*m+yy)].r);
                unionn((i-1)*m+j,(xx-1)*m+yy);
                if(a[find((i-1)*m+j)].l==1&&a[find((xx-1)*m+yy)].r==m)
                    flag=true;
                //cout<<i<<" "<<j<<" "<<a[find((i-1)*m+j)].l<<" "<<a[find((xx-1)*m+yy)].r<<endl;
            }
        }
    }
    int main()
    {
        int t,x,y;
        char s;
        scanf("%d",&t);
        while(t--)
        {
            flag=false;//初始化路没封 
            ans=0;
            scanf("%d%d",&n,&m);
            memset(map,0,sizeof(map));
            for(int i=1;i<=n;i++)
            {
                getchar();
                for(int j=1;j<=m;j++)
                {
                    scanf("%c",&s);
                    fa[(i-1)*m+j]=(i-1)*m+j;//初始化每个点的父结点是自己(可以理解成自己是一个集合) 
                    map[i][j]=s-'0';
                    if(map[i][j]==1)
                    {
                        a[(i-1)*m+j].l=a[(i-1)*m+j].r=j;//初始每个集合的左右边界 
                    }
                }
            }
            for(int i=1;i<=n;i++)//找可以合并的集合(或者树) 
            {
                for(int j=1;j<=m;j++)
                {
                    if(map[i][j]==1)
                    {
                        for(int k=0;k<8;k++)
                        {
                            int xx=i+dx[k];
                            int yy=j+dy[k];
                            if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&map[xx][yy]==1&&find((i-1)*m+j)!=find((xx-1)*m+yy))//寻找条件    
                            {
                                a[find((i-1)*m+j)].l=a[find((xx-1)*m+yy)].l=min(a[find((i-1)*m+j)].l,a[find((xx-1)*m+yy)].l);
                                a[find((i-1)*m+j)].r=a[find((xx-1)*m+yy)].r=max(a[find((i-1)*m+j)].r,a[find((xx-1)*m+yy)].r);
                                //更新最后这个合并集合的左右边界值 
                                unionn((i-1)*m+j,(xx-1)*m+yy);//连接两点 
                                if(a[find((i-1)*m+j)].l==1&&a[find((xx-1)*m+yy)].r==m)//判断路是否已经封死 
                                    flag=true;
                                //cout<<i<<" "<<j<<" "<<a[find((i-1)*m+j)].l<<" "<<a[find((i-1)*m+j)].r<<endl;
                            }
                        }
                    }
                }
            }
            scanf("%d",&q);
            for(int i=1;i<=q;i++)//询问 
            {
                scanf("%d%d",&x,&y);
                map[x+1][y+1]=1;//记得改变这点的值 
                a[x*m+y+1].l=a[x*m+y+1].r=y+1;
                if(!flag)//没封就一张找 
                {
                    ans++;
                    solve(x+1,y+1);    
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    按分类统计商品总数的性能优化思考
    Flash/Flex学习笔记(52):使用TweenLite
    Flash/Flex学习笔记(36):自己动手实现一个滑块控件(JimmySilder)
    解决JQuery中的ready函数冲突
    Flash/Flex学习笔记(41):碰撞检测
    Flash/Flex学习笔记(34):AS3中的自定义事件
    如何改变AspNetPager当前页码的默认红色?
    Flash/Flex学习笔记(42):坐标旋转
    Flash/Flex学习笔记(39):弹性运动
    C#检测SqlServer中某张表是否存在
  • 原文地址:https://www.cnblogs.com/xiongtao/p/9953415.html
Copyright © 2011-2022 走看看