HDU 5652 India and China Origins(二分+并查集||BFS)

http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=682&pid=1003

中文题意,不再描述。

题解:

  顺序给山峰出现的时间,明显地用二分来查找。然后连通块用并查集(也可以BFS,复杂度都是O(n))来维护。

1.并查集

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=505;
char maze[maxn][maxn];
bool vis[maxn][maxn];
int n,m,q,par[maxn*maxn];
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
struct node
{
    int x,y;
}p[maxn*maxn];
int find(int x)
{
    return x==par[x]?x:par[x]=find(par[x]);
}
void unite(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y)
        return ;
    par[x]=y;
}
bool check(int t)
{
    for(int i=0;i<=n*m+1;i++)
        par[i]=i;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(maze[i][j]=='1')
                vis[i][j]=true;
            else
                vis[i][j]=false;
    for(int i=1;i<=t;i++)
        vis[p[i].x][p[i].y]=true;
    for(int i=1;i<=n;i++)//最上方编号为0,1-n行编号为1-n*m,最后一行(n+1)编号为n*m+1
        for(int j=1;j<=m;j++)
        {
            if(vis[i][j])
                continue;
            for(int k=0;k<4;k++)
            {
                int nx=i+dx[k],ny=j+dy[k];
                if(ny<1||ny>m)
                    continue;
                if(nx==0)
                    unite((i-1)*m+j,0);
                else if(nx==n+1)
                    unite((i-1)*m+j,n*m+1);
                else if(!vis[nx][ny])
                        unite((i-1)*m+j,(nx-1)*m+ny);
            }
        }
    if(find(0)==find(n*m+1))
        return true;
    return false;
}
void solve()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%s",maze[i]+1);
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&p[i].x,&p[i].y);
        p[i].x++,p[i].y++;
    }
    if(check(q))//不存在解
    {
        cout<<"-1"<<endl;
        return ;
    }
    int l=1,r=q,ans=0;
    while(l<=r)//二分
    {
        int mid=(l+r)/2;
        if(!check(mid))
        {
            r=mid-1;
            ans=mid;
        }
        else
            l=mid+1;
    }
    cout<<ans<<endl;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(vis,false,sizeof(vis));
        solve();
    }
    return 0;
}

 2.BFS

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=505;
char maze[maxn][maxn];
bool vis[maxn][maxn];
int n,m,q;
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
struct node
{
    int x,y;
}p[maxn*maxn];
bool bfs()
{
    queue<node> que;
    node cur;
    for(int i=1;i<=n;i++)
    {
        cur.x=0;
        cur.y=i;
        que.push(cur);
    }
    while(que.size())
    {
        cur=que.front();
        que.pop();
        if(cur.x==n+1)
            return true;
        for(int i=0;i<4;i++)
        {
            node next=cur;
            next.x+=dx[i],next.y+=dy[i];
            if(0<=next.x&&next.x<=n+1&&1<=next.y&&next.y<=m&&!vis[next.x][next.y])
            {
                vis[next.x][next.y]=true;
                que.push(next);
            }
        }
    }
    return false;
}
bool check(int t)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(maze[i][j]=='1')
                vis[i][j]=true;
            else
                vis[i][j]=false;
    for(int i=1;i<=t;i++)
        vis[p[i].x][p[i].y]=true;
    return bfs();
}

void solve()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%s",maze[i]+1);
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&p[i].x,&p[i].y);
        p[i].x++,p[i].y++;
    }
    if(check(q))
    {
        cout<<"-1"<<endl;
        return ;
    }
    int l=1,r=q,ans=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(!check(mid))
        {
            r=mid-1;
            ans=mid;
        }
        else
            l=mid+1;
    }
    cout<<ans<<endl;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(vis,false,sizeof(vis));
        solve();
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/orion7/p/7344485.html