HDU 1198 并查集

/*

   学习李大牛每天复习之前写过的算法,每天找一题出来做做复习;

    *****并查集篇******

*/

这还算是一道简单的并查集,思路在代码中:

15MS 340K

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#define x m*(i-1)+j   
                       //define 实际上是字符替换,利用这一点将题中本应该是m*(i-1)+j的地方替换为x
                      //使得程序简洁
using namespace std;
char map[53][53];
struct squares
{
    bool u;
    bool d;
    bool l;
    bool r;
}s[11];  //存放 A-K 的田里渠道的方向
int f[3000];
int find(int a)   //查找 父亲函数
{
    if(f[a]==a) return a;
    else
        return f[a] = find(f[a]);
}
void set()  //按题目所给图 初始化 A-K 田里渠道的方向。未置为true的默认false
{
    s[0].u = s[0].l = s[1].u = s[1].r
    = s[2].l = s[2].d = s[3].d = s[3].r
    = s[4].u = s[4].d = s[5].l = s[5].r
    = s[6].l = s[6].r = s[6].u = s[7].u
    = s[7].l = s[7].d = s[8].l = s[8].r
    = s[8].d = s[9].u = s[9].d = s[9].r
    = s[10].u = s[10].d = s[10].l = s[10].r = true;
}

int main()
{
    set();
    int n,m;
    while(scanf("%d%d",&n,&m))
    {
        if(n==-1&&m==-1)
            break;
        for(int i = 1; i <= n; i++)
        {
            cin.get();
            for(int j = 1; j <= m; j++)
            {
                scanf("%c",&map[i][j]);
                f[x] = x;
            }
        }

        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
                if(s[map[i][j]-'A'].r==1&&s[map[i][j+1]-'A'].l==1)//向右方向查找
                {
                    int f1 = find(f[x+1]);
                    int f2 = find(f[x]);
                    if(j!=m&&f2!=f1)
                    {
                        f[f1] = f[f2];
                    }
                }
                if(s[map[i][j]-'A'].d==1&&s[map[i+1][j]-'A'].u==1)//向下方向查找
                {
                    int f1 = find(f[x+m]);
                    int f2 = find(f[x]);
                    if(i!=n&&f2!=f1)
                    {
                            f[f1] = f[f2];
                    }
                }
            }
        }
        int ans = 0;
        for(int i = 1; i <= n; i++)   //该点的父亲为自己,则说明这是某一片区的父节点 ans++
        {
            for(int j = 1; j <= m; j++)
            {
                if(find(x) == x)
                    ans++;
            }
        }
        printf("%d\n",ans);
    }
}


你可能感兴趣的:(HDU 1198 并查集)