【PAT】 Deepest Root (DFS)

【PAT】 Deepest Root (DFS)


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 . 

输入描述:
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.


输出描述:
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.

输入例子:
5
1 2
1 3
1 4
2 5

输出例子:
3
4
5

很巧妙的两边搜索。

首先题意:n个点搭建n-1条边。如果不构成树(一定构成了两个以上的连通图) 直接输出图的数量(用并查集解决即可

否则,已知树的深度是树根到叶子的最远距离,输出能得到最深的树的根节点编号。如果有多个结点可满足,都输出。


更进一步的,如果某个点u作为根,那么最深的那些叶子与u,一定是树中距离最远的点对。

这样不论我们以谁为根,最深的那些点,一定包括在上面提到的点对中。(*第一个迷

除了这些最深的点以外,相对于这些点距离最远的点,也是所需要得点(*第二个迷


想通了,求的话就好办了,两边dfs

预先选任意一个点为根

第一遍dfs找到最深的点(可能有多个),同时记录一下路径

第二遍dfs找到相对第一个dfs找到的那些点而言最远的点,可通过第一遍dfs标记的路径来找。如果在路径上,距离-1,否则距离+1


代码如下:

#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)
  
using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;
  
struct Edge
{
    int v,next;
};
  
int n;
int pre[10010];
int head[10010];
Edge eg[23333];
int dep[10010],to[10010];
int tp,cnt,mx,len[10010],cc;
  
void init()
{
    for(int i = 1; i <= n; ++i) pre[i] = i;
}
  
int Find(int x)
{
    return pre[x] == x? pre[x]: (pre[x] = Find(pre[x]));
}
  
void Add(int u,int v)
{
    eg[tp].v = v;
    eg[tp].next = head[u];
    head[u] = tp++;
}
  
void dfs1(int u,int pre,int depth)
{
    dep[u] = depth;
    to[u] = u;
  
    for(int i = head[u]; i != -1; i = eg[i].next)
    {
        if(eg[i].v == pre) continue;
        dfs1(eg[i].v,u,depth+1);
        if(dep[to[eg[i].v]] > dep[to[u]]) to[u] = to[eg[i].v];
    }
    if(dep[u] == mx) cnt++;
    else if(dep[u] > mx)
    {
        mx = dep[u];
        cnt = 1;
    }
}
  
void dfs2(int u,int pre,int l,bool op)
{
    len[u] = l;
    cc = max(cc,len[u]);
  
    if(!op)
    {
        cnt = 0;
        for(int i = head[u]; i != -1; i = eg[i].next)
        {
            if(eg[i].v == pre) continue;
            if(dep[to[eg[i].v]] == mx) cnt++;
        }
        if(cnt > 1) op = 1;
    }
  
    for(int i = head[u]; i != -1; i = eg[i].next)
    {
        if(eg[i].v == pre) continue;
        if(!op && dep[to[eg[i].v]] == mx) dfs2(eg[i].v,u,l-1,op);
        else dfs2(eg[i].v,u,l+1,op);
    }
}
  
int main()
{
    //fread();
    //fwrite();
  
    int u,v,k,r;
    scanf("%d",&n);
    init();
  
    memset(head,-1,sizeof(head));
  
    for(int i = 1; i < n; ++i)
    {
        scanf("%d%d",&u,&v);
        k = Find(u);
        r = Find(v);
        if(k != r) pre[r] = k;
        Add(u,v);
        Add(v,u);
    }
  
    cnt = 0;
    for(int i = 1; i <= n; ++i)
        if(Find(i) == i) cnt++;
  
    if(cnt > 1)
    {
        printf("Error: %d components\n",cnt);
    }
    else
    {
        mx = -1;
        dfs1(1,1,0);
      
        cc = -1;
        dfs2(1,1,mx,0);
        for(int i = 1; i <= n; ++i)
        {
            if(dep[i] == mx || len[i] == cc) printf("%d\n",i);
        }
    }
  
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值