zoukankan      html  css  js  c++  java
  • 思维+并查集 hdu5652

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

    题意:

      输入T,接下来T个样例,每个样例输入n,m代表图的大小,接下来n行,每行m个数,代表图,0表示这个位置可以走,1表示走不了,接下来q个点的位置,表示第q个时间这个点的值变成1,就不能走了,问在什么时间开始从最上面无法走到最下面。

    最后还是看了别人博客(不争气啊),用并查集的思路就是先给每个点编号,然后用两个数组pre1,pre2数组方便存储编号为i的点所在的点集(并查集)里面最左和最右的值,当最左的值为0,最右的值为m-1是说明这个连续的点集已经把上下隔断了。只是大致说了下,看代码,有人也用了二分+BFS,对q个时间段进行二分,用BFS判断上下是否被隔断,应该是这样,没用这种方法写。

    代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<set>
    #include<cstdio>
    #include<string>
    #include<deque> 
    using namespace std;
    typedef long long LL;
    #define eps 1e-8
    #define INF 0x3f3f3f3f
    #define maxn 505
    int n,m,k,t,ans,id;
    char str[maxn][maxn];
    int num[maxn][maxn];//记录点str[i][j]对应的编号 
    int pre1[maxn*maxn],pre2[maxn*maxn];//两个数组记录祖先,祖先编号对m取模得出的值就是左右两边最值 
    int dir[8][2]={0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,1,-1,-1};//八个方向 
    int find1(int a) 
    {
        if(a==pre1[a])
        return a;
        return pre1[a]=find1(pre1[a]);
    }
    void combine1(int x,int y)
    {
        int a=find1(x);
        int b=find1(y);
        if(a%m<b%m)//祖先编号对m取模值较小的为合并之后的祖先 
        pre1[b]=a;
        else
        pre1[a]=b;
    }
    int find2(int a)
    {
        if(a==pre2[a])
        return a;
        return pre2[a]=find2(pre2[a]);
    }
    void combine2(int x,int y)
    {
        int a=find2(x);
        int b=find2(y);
        if(a%m>b%m)//祖先编号对m取模值较大的为合并之后的祖先 
        pre2[b]=a;
        else
        pre2[a]=b;
    }
    void bianhao()
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                num[i][j]=++id;//给每个点编号 
                pre1[id]=id;
                pre2[id]=id;
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(str[i][j]=='1')
                {
                    for(int k=0;k<8;k++)//搜索每个黑块周围 
                    {
                        int a=i+dir[k][0];
                        int b=j+dir[k][1];
                        if(a>=0&&a<n&&b>=0&&b<m&&str[a][b]=='1')
                        {
                            combine1(num[i][j],num[a][b]);
                            combine2(num[i][j],num[a][b]);
                        }
                    }
                }
            }
        }
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            ans=-1;
            id=-1;
            for(int i=0;i<n;i++)
            scanf("%s",str[i]);
            bianhao();
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                {
                    int a=find1(num[i][j]);
                    int b=find2(num[i][j]);
                    if(a%m==0&&b%m==m-1)//在山峰升起前可能两国可能已经隔断 
                    {
                        ans=0;
                        break;
                    }
                }
                if(ans!=-1)
                break;
            }
            int q;
            scanf("%d",&q);
            for(int s=1;s<=q;s++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                str[x][y]='1';//山峰升起 
                if(ans!=-1)
                continue;
                for(int i=0;i<8;i++)
                {
                    int a=x+dir[i][0];
                    int b=y+dir[i][1];
                    if(a>=0&&a<n&&b>=0&&b<m&&str[a][b]=='1')
                    {
                        combine1(num[x][y],num[a][b]);
                        combine2(num[x][y],num[a][b]);
                        int l=find1(num[x][y]);
                        int r=find2(num[x][y]);
                        if(l%m==0&&r%m==m-1)//黑色块所在点集的左右两最值达到左右边界 
                        {
                            ans=s;
                            break;
                        }
                    }
                }    
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    java smtp 发送邮件
    Java 数据库连接配置
    kettle基础操作数据同步
    Java上传文件到服务器指定位置
    Java 操作word
    Java 导出Zip文件
    Java 遍历二叉树字符串
    一款基于vue.js 和node构建个人博客项目
    CSS选择器介绍和优先级
    CSS Position属性
  • 原文地址:https://www.cnblogs.com/6262369sss/p/9818480.html
Copyright © 2011-2022 走看看