计蒜客题解-T1260宗教信仰

题目概况

链接: https://nanti.jisuanke.com/t/T1260
难度: 普及/提高-(计蒜客评级普及T3,个人评价T2)

题目分析

简化题目: 有几群人,分别信仰不同的宗教,有几群人(细读题目就能发现)
涉及知识点: 图论、连通块、并查集
解题思路:
1. 题目告诉了我们那两人之间信仰宗教相同,我们可以借此建图(可行,比如A和B相同,B和C相同,那A和C就间接相同,等量代换)
2. DFS查询连通块数量即可

代码要点拆解

输入、建图属于预备知识,不讲

DFS查询连通块

针对DFS本身,我们要用vis数组记录,经过一个记一个,以免重复遍历

void dfs(int p) {
    vis[p] = true; //记录
    for (int i = 0; i < G[p].size(); i++) {
        int v = G[p][i]; //与p相连的每个点
        if (!vis[v]) { //避免重复 
            dfs(v); //继续遍历相连点
        }
    }
}

在主函数里需要这样操作:

      for (int i = 1; i <= n; i++) {
            if (!vis[i]) {
                ans++; //如果我一个dfs都完了你这个点还没遍历,那肯定属于另一群人,ans加1
                dfs(i); //dfs一遍这个点
            }
        }

收尾工作和数据的清除

由于我们一次评测有多组数据,前一次用的数据肯定得清除,回想一下我们用了哪些变量是要回收的?
1. vis数组
2.
3. ans

    cout << "Case " << ++indexx << ": " << ans << endl; //输出按格式
        for (int i = 1; i <= n; i++ ){
            vector<int>().swap(G[i]);
        } //swap大法让这个图释放内存,clear无效;这是个板子,可以记一下
        memset(vis, 0, sizeof(vis)); //memset函数yyds!
        ans = 0; //ans清零还能用

swap大法的详细讲解:https://blog.csdn.net/m0_37251750/article/details/100071023

完整代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#define asn ans //懒得改错,一劳永逸
using namespace std;

const int MAXN = 50002;
vector<int> G[MAXN];
bool vis[MAXN];
int n, m;
int ans, indexx;

void dfs(int p) {
    vis[p] = true;
    for (int i = 0; i < G[p].size(); i++) {
        int v = G[p][i];
        if (!vis[v]) {
            dfs(v);
        }
    }
}

int main() {
    while (1) {
        cin >> n >> m;
        if (n == 0 && m == 0) {
            break;
        }
        
        for (int i = 1; i <= m; i++) {
            int u, v;
            cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        } //建图
        for (int i = 1; i <= n; i++) {
            if (!vis[i]) {
                ans++;
                dfs(i);
            }
        }
        cout << "Case " << ++indexx << ": " << ans << endl;
        for (int i = 1; i <= n; i++ ){
            vector<int>().swap(G[i]);
        }
        memset(vis, 0, sizeof(vis));
        ans = 0;
    }
    return 0;
}

其他

本题笔者的第一反应就是DFS连通块,而且实现起来比并查集简单,如果大家有兴趣,可以尝试使用并查集解题(实现原理和连通块差不了多少)
并查集讲解:https://oi-wiki.org/ds/dsu/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oier_Asad.Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值