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;
}