HDU 1198 并查集

这篇博客主要介绍了如何利用并查集解决HDU 1198问题,博主通过代码详细阐述了解题思路,是并查集算法的实践复习案例。
摘要由CSDN通过智能技术生成

/*

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

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

*/

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

15MS340K

#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);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值