solution Of Pat 1021. Deepest Root (25)

48 篇文章 0 订阅

1021. Deepest Root (25)

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


结题思路:
题意要求我们找到在以某个节点为Root的情况下,保证树最高,输出全部这样的Root。
要求1:随意抓住一个节点,若有节点掉落,则无需进行的Deepest Root的判断;
要求2:随意抓住一个节点,往下延生最长的那个节点A必定是在Deepest Root的集合中;
若A不在,设A到根节点距离为LA,当前情况下,DR必定不会出现在根节点的与A同子树的子树中,设DR距离跟节点距离为LDR;
此时,抓住DR,往下延长最长的的那个节点B必然会是满足条件的一个根节点,距离原来的根节点为LB;
此时的最深的深度为depth=LDR+LB,然而LB<=LA,所以点A必然可以作为Deepest Root集合当中的一个。

程序步骤:
第一步、并查集判断这是一棵树还是森林;
第二步、随意找一个root,进行深搜,将最深的所有节点保存;
第三步、从保存节中随意选择一个,作为根,进行深搜,将最深的所有节点保存;
第四步、将第二步和第三部中的节点进行合并。
第五步、排序输出即可。

具体程序(AC)如下:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> node;//并查集使用的数组
vector<bool> deepRootSet;//标记为Deepest Root的集合
vector<int> ResultSet;//保存最后的Deepest Root
vector<int> deep;//保存每个节点的深度
vector<vector<int> > tree;//保存树的二维数组,用于深搜
vector<bool> visited;//节点访问标记符
int depth;//保存树的深度
int getParent(int a)
{
    if(node[a]!=a)
        return node[a]=getParent(node[a]);
    else
        return a;
}
void merge(int start,int end)
{
    int a=getParent(start);
    int b=getParent(end);
    if(a>b)
        node[a]=b;
    else
        node[b]=a;
}
int traverseTree(int root,int d)//深搜DFS,返回深度
{
    //cout<<root<<endl;
    deep[root]=d;
    visited[root]=true;
    bool flag=false;
    int max=-1;
    int depthTmp;
    for(int i=0;i<tree[root].size();++i)
    {
        if(!visited[tree[root][i]])
        {
            flag=true;
            depthTmp=traverseTree(tree[root][i],d+1);
            if(depthTmp>max)
                max=depthTmp;
        }
    }
    if(!flag)
        return d;
    return max;
}
int main()
{
    int n;
    cin>>n;
    if(n==0)
        return 0;
    tree.resize(n+5);
    visited.resize(n+5,0);
    deep.resize(n+5,-1);
    deepRootSet.resize(n+5,0);
    node.resize(n+5);
    for(int i=1;i<=n;++i)
        node[i]=i;
    int start,end;
    for(int i=1;i<n;++i)
    {
        cin>>start>>end;
        tree[start].push_back(end);
        tree[end].push_back(start);
        merge(start,end);
    }
    int cons=0;
    for(int i=1;i<=n;++i)
        if(node[i]==i)
            ++cons;
    if(cons>1)
    {
        cout<<"Error: "<<cons<<" components"<<endl;
        return 0;
    }
    //森林判断结束
    depth=traverseTree(1,0);//深搜过程中保存节点深度,返回最深的深度
    int newRoot=1;
    for(int i=1;i<=n;++i)
    {
        if(deep[i]==depth)
        {
            newRoot=i;
            deepRootSet[i]=true;//放入到集合进行标记
        }
    }
    visited.clear();
    visited.resize(n+5,0);
    depth=traverseTree(newRoot,0);//二次深搜,判断结束
    for(int i=1;i<=n;++i)
    {
        if(deep[i]==depth)
            deepRootSet[i]=true;
    }
    ResultSet.clear();
    for(int i=1;i<=n;++i)
        if(deepRootSet[i])
            ResultSet.push_back(i);
    sort(ResultSet.begin(),ResultSet.end());
    for(int i=0;i<ResultSet.size();++i)
        cout<<ResultSet[i]<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值