hdu1198—并查集

华电北风吹
天津大学认知计算与应用重点实验室
日期:2015/09/17

原题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1198
初始一个和矩阵方格数相等的一维数组,矩阵每个下标代表矩阵每个方块,一维数组每个元素的值代表当前节点的父节点。初始时,每个节点都是根节点(父节点是本身)。
这样做的优点:
集合合并的话只需要将两个集合的根节点的其中一个修改为另一个即可。
计算联通分量个数只需要遍历数组,计数根节点个数即可。
C++ code:

#include <iostream>
#include <fstream>
using namespace std;

#include<string.h>

char str[2][9] = { { "ABEGHJK" }, { "ACFGHIK" } };
int f[2505], m, n;
char map[52][52];

int check(int x, int y)
{
    if (x >= 0 && x<m && y >= 0 && y<n)
        return 1;
    return 0;
}

int getFather(int a)
{
    while (a != f[a])
        a = f[a];
    return a;
}

void Union(int a, int b)
{
    int root1 = getFather(a);
    int root2 = getFather(b);
    if (root1 != root2)
    {
        if (root1<root2)
            f[root2] = root1;
        else
            f[root1] = root2;
    }
}

int judge(char c, int flag)
{
    int i;
    for (i = 0; i<7; i++)
    {
        if (str[flag][i] == c)
            return i + 1;
    }
    return 0;
}

void process()
{
    int i, j, dx, dy;
    char c;
    for (i = 0; i <= n*m; i++)
        f[i] = i;
    for (i = 0; i<m; i++)
    {
        for (j = 0; j<n; j++)
        {
            c = map[i][j];
            if (c == 'C' || c == 'D' || c == 'E' || c == 'H'|| c == 'I' || c == 'J' || c == 'K')
            {
                dx = i + 1;
                dy = j;
                if (check(dx, dy))
                {
                    if (judge(map[dx][dy], 0))
                    {
                        Union(i*n + j, dx*n + dy);
                    }
                }
            }
            if (c == 'B' || c == 'D' || c == 'F' || c == 'G'|| c == 'I' || c == 'J' || c == 'K')
            {
                dx = i;
                dy = j + 1;
                if (check(dx, dy))
                {
                    if (judge(map[dx][dy], 1))
                    {
                        Union(i*n + j, dx*n + dy);
                    }
                }
            }
        }
    }
    int result = 0;
    for (i = 0; i<n*m; i++)
        if (f[i] == i)
            result++;
    cout << result << endl;
}
int main()
{
    ifstream in(".\\input.txt");
    cin.rdbuf(in.rdbuf());

    while (cin>>m>>n)
    {
        if (m<0 || n<0)
            break;
        cin.ignore();
        for (int i = 0; i < m; i++)
            cin.getline(map[i], 255);
        process();
    }
    system("pause");
    return 0;
}

python code:

def mainfunc(filename):
    file=open(filename,'r')
    while True:
        line=file.readline().strip('\n')
        if len(line)==0:
            continue
        if line=="-1 -1":
            break
        line=line.split()
        M,N=int(line[0]),int(line[1])
        type=[file.readline().strip('\n') for i in range(M)]
        Func(M,N,type)
    file.close()

def Findroot(leader,i):
    while leader[i]!=i:
        i=leader[i]
    return i

def JudgeVerticalUnion(type,row,col):
    if type[row][col] in 'CDEHIJK':
        if type[row+1][col] in 'ABEGHJK':
            return True
    return False

def JudgeHorizonlUnion(type,row,col):
    if type[row][col] in 'BDFGIJK':
        if type[row][col+1] in 'ACFGHIK':
            return True
    return False

def Union(leader,p1,p2):
    f1=Findroot(leader,p1)
    f2=Findroot(leader,p2)
    if f1<f2:
        leader[f2]=f1
    else:
        leader[f1]=f2

def Func(M,N,type):
    leader=[i for i in range(M*N)]
    for row in range(M):
        for col in range(N):
            if row+1<M:
                if JudgeVerticalUnion(type,row,col):
                    p=row*N+col
                    Union(leader,p,p+N)
            if col+1<N:
                if JudgeHorizonlUnion(type,row,col):
                    p=row*N+col
                    Union(leader,p,p+1)
    result=0
    for i in range(M*N):
        if leader[i]==i:
            result+=1
    print(result)

mainfunc('input.txt')

项目代码下载:
https://github.com/ncepuzhengyi/ProblemSet/tree/master/ProblemSet/hdu1198
参考网址:
http://blog.csdn.net/njdragonfly/article/details/5442761

你可能感兴趣的:(hdu1198—并查集)