PAT 甲级1021 Deepest Root

PAT 甲级1021 Deepest Root

给定N个节点和N-1条边,找到其中的最深根节点——该根节点使整个树的深度最大

先判断该图是否是一颗树,即判断连通分量个数,如果连通分量个数大于1,则说明出现了循环图,不能构成树

如果联通分量为1,就要找最深根节点,需要两次dfs。

第一次dfs从任意节点出发,**找到深度最大的叶子节点们,**然后从这些叶子节点中任意选择一个,开始dfs,再次找到深度最大的叶子节点们

最终结果是两次dfs结果的 并集——使用set

// 1021 Deepest Root.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
int n, maxheight = 0;
vector<vector<int>> v;  //记录每个节点的邻接节点
bool visit[10010]; //记录dfs中每个节点的访问情况
set<int> s; //并查集
vector<int> temp; //记录深度最大的节点
void dfs(int node, int height) {
    if (height > maxheight) { //更新
        temp.clear();
        temp.push_back(node);
        maxheight = height;
    }
    else if (height == maxheight) { //添加深度最大节点
        temp.push_back(node);
    }
    visit[node] = true;
    for (int i = 0; i < v[node].size(); i++) {
        if (visit[v[node][i]] == false) { //因为是无向图,节点的邻接节点可能被访问过
            dfs(v[node][i], height + 1);
        }
    }
}

int main()
{
    cin >> n;
    v.resize(n + 1);
    int a, b, s1 = 0, cnt = 0;
    for (int i = 0; i < n - 1; i++) {
        cin >> a >> b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    for (int i = 1; i <= n; i++) {
        if (visit[i] == false) {
            dfs(i, 1);
            if (i == 1) {
                if (temp.size() != 0) s1 = temp[0]; //s1为第二次dfs的根节点
                for (int j = 0; j < temp.size(); j++) {
                    s.insert(temp[j]); //将第一次dfs结果插入set
                }
            }
            cnt++; //记录连通分量个数
        }
    }
    if (cnt >= 2) printf("Error: %d components", cnt);
    else {
        temp.clear(); //清空temp,准备第二次dfs
        maxheight = 0;
        fill(visit, visit + 10010, false);
        dfs(s1, 1);
        for (int i = 0; i < temp.size(); i++) s.insert(temp[i]); //将第二次dfs结果插入set
        for (auto it = s.begin(); it != s.end(); it++) {
            cout << *it << endl; //输出结果
        }
    }
    return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

关于set的理解

算法学习笔记(1) : 并查集 - 知乎 (zhihu.com)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值