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;
    }
  • 相关阅读:
    107. Binary Tree Level Order Traversal II
    108. Convert Sorted Array to Binary Search Tree
    111. Minimum Depth of Binary Tree
    49. Group Anagrams
    使用MALTAB标定实践记录
    442. Find All Duplicates in an Array
    522. Longest Uncommon Subsequence II
    354. Russian Doll Envelopes
    opencv 小任务3 灰度直方图
    opencv 小任务2 灰度
  • 原文地址:https://www.cnblogs.com/6262369sss/p/9818480.html
Copyright © 2011-2022 走看看