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

来源:互联网 发布:网络禁书40百度云 编辑:程序博客网 时间:2024/05/22 15:47

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_JUDGEfreopen("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 + jchar 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;}
0 0