码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 510B 无向图找环的两种方法(搜索与并查集)

时间:2015-08-13 22:22:09      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:acm   dfs   并查集   codeforces   图论   

题目连接:http://codeforces.com/problemset/problem/510/B

解法:

  1. dfs
    每次把父节点的值记录并传递下去,判断一下新达到节点:
    (1)没有走过 → 继续搜索;
    (2)走过&&不是父节点(对于本题步数也要>=4) → 找到环;
  2. 并查集
    每个节点映射成 i*m+j从起点开始分别把它下面与于右面的节点加进来,如果发现有节点已经在集合中,那么环已经找到了。

    • DFS:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
//////////////////////
#include<iostream>
#include<algorithm>
#include<string>
#include <iterator>
#include<sstream>
#include<functional>
#include<numeric>
///////////////////////
#include<vector>
#include<map>
#include <stack>
#include<queue>
#include<set>
#include <bitset>
#include <list>
using namespace std;
#define lch(x)  ((x) << 1)
#define rch(x) ((x)<<1|1)
#define dad(x) ((x)>>1)
#define lowbit(x) ((x)&(-x))
typedef  long long int LL;
const int INF = 0x4f4f4f4f ;
const double eps = 1e-6;
const long double PI = acos(0.0) * 2.0;
const int N = 100+10;
int n,m;
char maze[N][N];
bool vis[N][N];
const int dx[] = {0,1,0,-1};
const int dy[] = {1,0,-1,0};
bool ok;
bool dfs(int x ,int y,int px,int py,int cnt);
int main()
{
    //freopen("in.txt", "r", stdin);
    while(scanf("%d%d%*c",&n,&m) == 2)
    {
        memset(vis,0,sizeof(vis));
        for(int i = 0 ; i < n ; i++)
            gets(maze[i]);

        ok = 0;
        for(int i = 0 ; i < n ; i++)
            for(int j = 0 ; j < m ; j++)
                if(!vis[i][j])
                    if(dfs(i,j,-1,-1,1))  
                    {
                        puts("Yes");
                        return 0;
                    }

        puts("No");
    }
    return 0;
}

bool dfs(int x ,int y,int px,int py,int cnt)
{
    vis[x][y] = 1;
    for(int i = 0 ; i < 4 ; i++)
    {
        int nx = x +dx[i] , ny = y + dy[i];

        if(0<= nx && nx < n && 0 <= ny && ny < m && maze[nx][ny] == maze[x][y])
        {
            if(!vis[nx][ny])    dfs(nx,ny,x,y,cnt+1);
            else if( (nx != px || ny != py) && cnt>=4)     ok = 1;
        }
    }
    return ok;
}
  • 并查集:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
//////////////////////
#include<iostream>
#include<algorithm>
#include<string>
#include <iterator>
#include<sstream>
#include<functional>
#include<numeric>
///////////////////////
#include<vector>
#include<map>
#include <stack>
#include<queue>
#include<set>
#include <bitset>
#include <list>
using namespace std;
#define lch(x)  ((x) << 1)
#define rch(x) ((x)<<1|1)
#define dad(x) ((x)>>1)
#define lowbit(x) ((x)&(-x))
typedef  long long int LL;
const int INF = 0x4f4f4f4f ;
const double eps = 1e-6;
const long double PI = acos(0.0) * 2.0;
const int N = 10000+10;

int pre[N];
int _rank[N];
char maze[N][N];
int find(int x);
int join(int x,int y);
void ini(void);
int same(int x,int y);

int main()
{
    ini();
    int n,m;
    scanf("%d%d%*c",&n,&m);

    for(int i = 0 ; i < n ; i++)
        gets(maze[i]);

    for(int i = 0 ; i < n ; i++)
    {
        for(int j = 0 ; j < m ; j++)
        {
            if(maze[i][j] == maze[i+1][j] && i <n-1)
            {
                if(same(i*m+j,(i+1)*m+j))   {puts("Yes");return 0; }
                else join(i*m+j,(i+1)*m+j);
            }

            if(maze[i][j] == maze[i][j+1] && j < m-1)
            {
                if(same(i*m+j,i*m+j+1))   {puts("Yes");return 0; }
                else join(i*m+j,i*m+j+1);
            }
        }
    }
    puts("No");
    return 0;
}


void ini(void)
{
    int i;

    for(i = 0 ; i < N ; i++)
        pre[i] = i,_rank[i]=0;
}

int join(int x,int y)
{
    int fx = find(x),fy = find(y);

    if(fx == fy)
        return 0;

    if(_rank[fx] > _rank[fy])
    {
        pre[fy] = fx;
    }
    else
    {
        pre[fx] = fy;
        if(_rank[fx] == _rank[fy])
            _rank[fy]++;
    }
}

//简化写法,使用递归
// int find(int x){ return x==pre[x]?x:pre[x]=find(pre[x]); }

int find (int x)
{
    int r = x;

    while(r != pre[r])
        r = pre[r];

    int i = x,j;

    while( r != pre[i])
    {
        j = pre[i];
        pre[i] = r;
        i = j;
    }

    return r;
}

int same(int x,int y)
{
    return find(x) == find(y);
}

版权声明:本文为博主原创文章,允许非商业性转载,转载必须注名作者(CSDN tt2767)与本博客链接:http://blog.csdn.net/tt2767。

CodeForces 510B 无向图找环的两种方法(搜索与并查集)

标签:acm   dfs   并查集   codeforces   图论   

原文地址:http://blog.csdn.net/tt2767/article/details/47610569

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!