PAT甲级练习题A1021. Deepest Root (25)

2 篇文章 0 订阅
1 篇文章 0 订阅

题目描述

A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<=10000) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N-1 lines follow, each describes an edge by given the two adjacent nodes’ numbers.

Output Specification:

For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print “Error: K components” where K is the number of connected components in the graph.

Sample Input 1:
5
1 2
1 3
1 4
2 5
Sample Output 1:
3
4
5
Sample Input 2:
5
1 3
1 4
2 5
3 4
Sample Output 2:
Error: 2 components

题目解析

原来自己使用宽度搜索,然后全部迭代一遍深度,超时了;
看了_Occult_的解法,知道树的直径的证明解法,以任意一点为起点遍历找到深度最深的子叶都是最长路径的两端之一,再从找到的子叶中选一个作为起点再进行一次遍历,找到深度最深的子叶也是最长路径的两端之一,去掉重复的就OK了。
还有学习了使用并查集确定无向图的连通块。原来我是利用visit数组使用深度遍历找。

代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N_max = 10000 + 10;
int map[N_max][N_max];
int father[N_max];
int deep_max;
int deep[N_max];
int N;

int find_father(int kid)
{
    if (kid == father[kid])
        return kid;
    else
    {
        return father[kid] = find_father(father[kid]);
    }
}


void dfs(int a,int b, vector<int>&vis)
{
    if (vis[b] != 0)return;
    else
    {
        deep[b] = deep[a] + 1;
        if (deep[b] > deep_max)
        {
            deep_max = deep[b];
        }
        vis[b] = 1;
        for (int i = 1; i <= N; ++i)
        {
            if (map[b][i] == 1)
            {
                dfs(b, i, vis);
            }
        }
    }
}

int main()
{
    //生成图

    cin >> N;
    for (int i = 1; i < N; ++i)
    {
        int x, y;
        scanf_s("%d %d", &x, &y);
        map[x][y] = map[y][x] = 1;
    }
    //并查集统计无向图的连通块:1.初始化为N个树,每个树的根节点为自己;2.find_father()找到根节点;
    //3.合并树;4.压缩路径将所有节点直接指向根节点,可在find_father()中使用递归完成;
    for (int i = 1; i <= N; ++i)
    {
        father[i] = i;
    }

    int cnt = N;
    for (int i = 1; i <= N; ++i)
    {
        for (int j = 1; j < i; ++j)
        {
            int fa_i= find_father(i), fa_j = find_father(j);

            if (map[i][j] == 1 &&  fa_i!=fa_j)
            {
                --cnt;
                father[fa_i] = fa_j;
            }
        }
    }

    if (cnt > 1)
    {
        printf_s("Error: %d components", cnt);
    }
    else
    {
        vector<int> vis(N + 1, 0);
        dfs(1,1, vis);
        vector<int>root;
        for (int i = 1; i <= N; ++i)
        {
            if (deep[i] == deep_max)
            {
                root.push_back(i);
            }
        }

        vector<int> vis2(N + 1, 0);
        dfs(root[0],root[0], vis2);
        for (int j = 1; j <= N; ++j)
        {
            if (deep[j] == deep_max&&find(root.begin(), root.end(), j) == root.end())
            {
                root.push_back(j);
            }
        }

        sort(root.begin(), root.end());
        for (int i = 0; i < root.size(); ++i)
        {
            printf_s("%d\n", root[i]);
        }
    }
    system("pause");
    return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值