【总结向】PAT甲级并查集 1013和1118

1.1013 Battle Over Cities
在这里插入图片描述思路:
N个点M个边K次查询,每次查询的结果等价于孤立点的个数-1
外循环:每次查询,内循环:存连通除查询点外的所有边,最终输出孤立点个数-1 O(KM)<1e8

代🐎:

// N个点M个边K次查询,每次查询的结果等价于孤立点的个数-1
// 外循环:每次查询,内循环:存连通除查询点外的所有边,最终输出孤立点个数-1 O(KM)<1e8

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

const int N = 1010;
const int M = 500010;
int fa[N];
struct Edge{
    
    int a, b;
}e[M];

int find(int x)
{
    if(fa[x] != x) fa[x] = find(fa[x]);
    return fa[x]; // 返回的是fa[x]而不是x
}

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    
    
    for(int i = 0; i < m; i++)
    {
        scanf("%d %d", &e[i].a, &e[i].b);
    }
    
    while(k --)
    {
        int city;
        cin >> city;
    
        for(int i = 1; i <= n; i ++) fa[i] = i; // 每次循环都要初始化
        
        int cnt = n - 1;
        for(int j = 0; j < m; j ++)
        {   
            if(e[j].a != city && e[j].b != city)
            {
                int pa = find(e[j].a);
                int pb = find(e[j].b);
                if(pa != pb) // 不连通就合并
                {
                    fa[pa] = pb;
                    cnt --;
                }

            }
        }
        
        cout << cnt - 1 << endl;
    }
    return 0;
}

2.PAT 1118 Birds in Forest
在这里插入图片描述思路:
并查集:也是统计连通块数目,树的数目=连通块个数,鸟的个数用hash和sum维护一下,询问即判定是否连通
复杂度 O(NK + Q) = 1e5

代🐎:

// 并查集:也是统计连通块数目,树的数目=连通块个数,鸟的个数用hash和sum维护一下,询问即判定是否连通
// 复杂度 O(NK + Q) = 1e5
#include <iostream>
#include <cstring>
using namespace std;

const int N = 10010;
int fa[N], b[N];
bool st[N];

int find(int x)
{
    if(fa[x] != x) fa[x] = find(fa[x]);
    return fa[x];
}


int main()
{
    int n, k, q;
    cin >> n;
    
    for(int i = 1; i <= N; i ++) fa[i] = i;
    memset(st, 0, sizeof st);
    
    int birds = 0;
    for(int i = 1; i <= n; i ++)
    {
        cin >> k;
        
        for(int j = 1; j <= k; j ++)
        {
            cin >> b[j];
            int bird = b[j];
            if(!st[bird]) birds ++;
            st[bird] = true;
        }
        
        for(int j = 1; j < k; j ++) // 连通同一棵树上所有鸟
        {
            int p = b[j], q = b[j + 1];
            p = find(p), q = find(q);
            if(p != q)
            {
                fa[p] = q;
            }
        }
    }
    
    int trees = 0;
    for(int i = 1; i <= birds; i ++)
    {
        if(fa[i] == i) trees ++;
    }
    cout << trees << " " << birds << endl;
    
    
    
    cin >> q;
    while(q --)
    {
        int x, y;
        cin >> x >> y;
        int px = find(x), py = find(y);
        if(px == py) cout << "Yes" << endl;
        else cout << "No" << endl;
        
    }
    
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值