• hdu 5652 India and China Origins 并查集


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

    题目大意:n*m的矩阵上,0为平原,1为山。q个询问,第i个询问给定坐标xi,yi,表示i年后这里的平原上会长出山。问第几年以后印度和中国交流会被阻碍

    思路:(官方题解)这是一个连通性的问题。你会发现如果将所有操作逆序来看的话就很容易用并查集来处理了。 首先把所有的山峰都加到图中,然后逆序处理每个操作: 对某次操作,在图中删除该位置的山峰,然后判断两个点是否联通,一旦联通就得到了结果。 这里需要对China和India分别新建一个对应的节点。特殊处理代码注释见分晓

    /**************************************************************
        Problem:hdu 5652
        User: youmi
        Language: C++
        Result: Accepted
        Time:93MS
        Memory:3504K
    ****************************************************************/
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#include<bits/stdc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <stack>
    #include <set>
    #include <sstream>
    #include <cmath>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #define zeros(a) memset(a,0,sizeof(a))
    #define ones(a) memset(a,-1,sizeof(a))
    #define sc(a) scanf("%d",&a)
    #define sc2(a,b) scanf("%d%d",&a,&b)
    #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scs(a) scanf("%s",a)
    #define sclld(a) scanf("%I64d",&a)
    #define pt(a) printf("%d
    ",a)
    #define ptlld(a) printf("%I64d
    ",a)
    #define rep0(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define rep_1(i,n) for(int i=n;i>=1;i--)
    #define rep_0(i,n) for(int i=n-1;i>=0;i--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define lson (step<<1)
    #define rson (lson+1)
    #define esp 1e-6
    #define oo 0x3fffffff
    #define TEST cout<<"*************************"<<endl
    
    using namespace std;
    typedef long long ll;
    
    int n,m,q;
    
    const int maxn=500+10;
    int img[maxn][maxn];
    int fa[maxn*maxn];
    int s=0,t=n*m+1;
    struct node
    {
        int id;
        int x,y;
        void init(int _id,int _x,int _y)
        {
            id=_id,x=_x,y=_y;
        }
    }p[maxn*maxn];
    void init()
    {
        for(int i=0;i<=n+1;i++)
            for(int j=1;j<=m;j++)
                fa[i*m+j]=i*m+j;
        /**
        将第0排看做起点,第n+1排作为终点,
        并分别以对应行最小的1和(n+1)*m+1为代表,
        因为我的合并函数是以坐标大小来合并两棵树的
        */
        for(int j=1;j<=m;j++)
            img[0][j]=0;
        for(int j=1;j<=m;j++)
            img[n+1][j]=0;
        s=1,t=(n+1)*m+1;
        fa[s]=s;fa[t]=t;
    }
    int get_f(int x)
    {
        while(x!=fa[x])
        {
            fa[x]=get_f(fa[x]);
            x=fa[x];
        }
        return x;
    }
    void Union(int x,int y)
    {
        int f1=get_f(x);
        int f2=get_f(y);
        if(f1>f2)
            fa[f1]=f2;
        else
            fa[f2]=f1;
    }
    int kx[]={1,-1,0,0};
    int ky[]={0,0,-1,1};
    bool isIn(int x,int y)
    {
        if(x<0||x>n+1||y<1||y>m)
            return false;
        return true;
    }
    bool vis[maxn*maxn];
    void dfs(int x,int y)
    {
        vis[x*m+y]=1;
        int curx,cury;
        for(int k=0;k<4;k++)
        {
            curx=x+kx[k];
            cury=y+ky[k];
            if(isIn(curx,cury)&&img[curx][cury]==0)
            {
                Union(curx*m+cury,x*m+y);
                if(!vis[curx*m+cury])
                    dfs(curx,cury);
            }
        }
    }
    bool work()
    {
        init();
        zeros(vis);
        for(int i=0;i<=n+1;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(img[i][j]==0&&!vis[i*m+j])
                {
                    dfs(i,j);
                }
            }
        }
        if(fa[s]==fa[t])
            return false;
        else
            return true;
    }
    void prt()
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                printf("%d ",img[i][j]);
            cout<<endl;
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        #endif
        int T_T;
        scanf("%d",&T_T);
        for(int kase=1;kase<=T_T;kase++)
        {
            sc2(n,m);
            getchar();
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                    img[i][j]=getchar()-'0';
                getchar();
            }
            sc(q);
            int x,y;
            for(int i=1;i<=q;i++)
            {
                sc2(x,y);
                x++,y++;
                p[i].init(i,x,y);
                img[x][y]=1;
            }
            //prt();
            if(!work())
            {
                puts("-1");
                continue;
            }
            int flag=1;
            for(int i=q;i>=1;i--)
            {
                x=p[i].x,y=p[i].y;
                img[x][y]=0;
                get_f(x*m+y);
                int curx,cury;
                /**
                在恢复为平原时,只需要查看相邻4个点就好了,
                因为在第一次dfs的时候把所有为0的点都处理过了
                而新出现的0的点只需合并到相邻点的树里就好了
                */
                for(int k=0;k<4;k++)
                {
                    curx=x+kx[k];
                    cury=y+ky[k];
                    if(isIn(curx,cury)&&img[curx][cury]==0)
                    {
                        Union(curx*m+cury,x*m+y);
                    }
                }
                if(get_f(s)==get_f(t))
                {
                    printf("%d
    ",i);
                    flag=0;
                    break;
                }
            }
            if(flag)
                puts("0");
        }
    }
    不为失败找借口,只为成功找方法
  • 相关阅读:
    Redis应用----消息传递
    Memcache存储机制与指令汇总
    文本挖掘预处理之向量化与Hash Trick
    证书(Certificate)与描述文件(Provisioning Profiles)
    IOS使用命令行打包
    IOS使用xcode编译代码
    IOS使用SourceTree
    docker修改docker0 mtu
    linux开机自启动
    设计模式
  • 原文地址:https://www.cnblogs.com/youmi/p/5343336.html
Copyright © 2020-2023  润新知