PAT A1118 Birds in Forest (25 分) 并查集

本文介绍了一个使用并查集数据结构解决鸟群分类问题的算法。通过处理N张照片上的鸟编号,该算法能够找出最大鸟群数量及鸟总数,并判断任意两只鸟是否属于同一群。代码实现中,采用路径压缩优化,有效避免了超时问题。

    题目大意:给出N张照片,每张照片上有一些鸟的编号(<10^4),同一张照片上的鸟被认为属于同一棵树,求出最大有多少棵树和多少只鸟,并判断给出的两只鸟是否属于同一棵树。

    常规并查集问题,如果不用路径压缩的话测试点3会超时。

AC代码:

#include <vector>
#include <cstdio>

using namespace std;

const int MAXN = 10010;
vector<int> parent(MAXN);

int findParent(int p)
{
    int a = p;
    while(p != parent[p])
    {
        parent[p] = parent[parent[p]];
        p = parent[p];
    }
    return p;
}

void unionElement(int a, int b)
{
    int aRoot = findParent(a);
    int bRoot = findParent(b);
    parent[aRoot] = bRoot;
}

int main()
{
    int N;
    scanf("%d", &N);
    vector<bool> hasAppeared(MAXN, 0);
    vector<bool> roots(MAXN, 0);
    int birdsCnt = 0;
    int rootsCnt = 0;
    for (int i = 0; i < MAXN; ++i)
        parent[i] = i;
    for (int i = 0; i < N; ++i)
    {
        int cnt;
        scanf("%d", &cnt);
        int id;
        scanf("%d", &id);
        if(!hasAppeared[id])
        {
            hasAppeared[id] = true;
            birdsCnt++;
        }
        for (int j = 1; j < cnt; ++j)
        {
            int other;
            scanf("%d", &other);
            if(!hasAppeared[other])
            {
                hasAppeared[other] = true;
                birdsCnt++;
            }
            unionElement(id, other);
        }
    }
    for (int i = 0; i < MAXN; ++i)
    {
        if(hasAppeared[i])
        {
            int iRoot = findParent(i);
            if(!roots[iRoot])
            {
                rootsCnt++;
                roots[iRoot] = true;
            }
        }
    }
    printf("%d %d\n", rootsCnt, birdsCnt);
    int Q;
    scanf("%d", &Q);
    for (int query = 0; query < Q; ++query)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        if(findParent(u) == findParent(v)) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值