Codeforces Round #290 (Div. 2)B - Fox And Two Dots——并查集/搜索

http://codeforces.com/contest/510/problem/B

给你一张地图,判断是否存在一个圈

我的劣质代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
char mp[55][55];
int vis[55][55];
int dirx[]={0,0,1,-1};
int diry[]={1,-1,0,0};
bool flag;
int sx,sy;
char colc;
struct node{
    int x,y;
}p[55][55];
void print_ans(int x,int y){
    if(p[x][y].x==x&&p[x][y].y==y) return ;
    print_ans(p[x][y].x,p[x][y].y);
    printf("%d%d -->",x,y);
}
bool check(int x,int y){
    if(x>=0&&x<n&&y>=0&&y<m&&mp[x][y]==colc) return true;
    return false;
}

bool dfs(int x,int y,int cnt){
    if(flag) return true;
    for(int i=0;!flag&&i<4;++i){
        int vx=x+dirx[i];
        int vy=y+diry[i];
        if(vx==sx&&vy==sy&&cnt>=4) {flag=true;return true;}
        if(!check(vx,vy)) continue;
        if(!vis[vx][vy]){
            vis[vx][vy]=1;
            if(dfs(vx,vy,cnt+1)) return true;
            if(dfs(x,y,cnt)) return true;
        }
    }
    return false;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
    cin>>n>>m;
    for(int i=0;i<n;++i) scanf("%s",mp[i]);
    flag=false;

    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            memset(vis,0,sizeof(vis));
            sx=i,sy=j;
            colc=mp[i][j];
            p[i][j].x=i;
            p[i][j].y=j;
            vis[i][j]=1;
            if(dfs(i,j,1)){printf("Yes\n");return 0;}
        }
    }

    printf("No\n");
    return 0;
}
除非往回走,否则只有走了一个圈,才有可能走到以前走过的点,因为只有4个方向可以走
#include<bits/stdc++.h>
using namespace std;
int n,m;
char pic[55][55];
int vis[55][55];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
bool dfs(int x,int y,int px,int py,char c){
    vis[x][y]=1;
    for(int i=0;i<4;++i){
        int tx=x+dx[i];
        int ty=y+dy[i];
        if(tx>=0&&tx<n&&ty>=0&&ty<m&&(pic[tx][ty]==c)&&(tx!=px||ty!=py)){
            if(vis[tx][ty]) return true;
            if(dfs(tx,ty,x,y,c)) return true;
        }
    }
    return false;
}

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;++i) scanf("%s",pic[i]);
    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            if(!vis[i][j])
                if(dfs(i,j,-1,-1,pic[i][j])){
                    printf("Yes\n");
                    return 0;
                }
        }
    }
    printf("No\n");
    return 0;
}
两个方向的并查集
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int n, m;

#define FOR(x, y, z) for(int x = y; x <= z; x ++)
#define p(i, j) (i - 1) * m + j

char a[60][60];
int fa[3600];
int yy = 0;

int find(int x){
    if(x == fa[x]) return x;
    int k = find(fa[x]);
    fa[x] = k;
    return k;
}

void insert(int i, int j){
    int x = find(i), y = find(j);
    if(x == y) {
        yy = 1;
        return;
    }
    fa[x] = y;
}

int main(){
    scanf("%d %d", &n, &m);
    char ch;
    scanf("%c", &ch);
    FOR(i, 1, n){
        FOR(j, 1, m){
            scanf("%c", &a[i][j]);
        }
        scanf("%c", &ch);
    }
    FOR(i, 1, n)
        FOR(j, 1, m)
            fa[p(i, j)] = p(i, j);
    FOR(i, 1, n)
        FOR(j, 1, m){
            if(j < m && a[i][j] == a[i][j + 1]) insert(p(i, j), p(i, j + 1));
            if(i < n && a[i][j] == a[i + 1][j]) insert(p(i, j), p(i + 1, j));
        }
    if(yy == 1) printf("Yes\n");
    else printf("No\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值