题意:给定一棵树,求树的中心(即到各结点的距离最小)。若存在多个,按顺序输出。(至多两个,依据树的性质)。
思路:树的中心必然为其直径的中点,利用两个DFS求直径的两个结点及其直径长,DFS(1)求出树的最远结点,DFS(2)以该结点为起始,寻找离该结点的最远点,依据直径长循环,输出中点。
#include <iostream>
#include <vector>
#define maxn 10010
using namespace std;
vector <int> tree[maxn];
int n,v,l,parent[maxn];
bool visit[maxn];
void DFS(int x,int father,int deep){
visit[x]=1;
parent[x]=father;
if(deep>l){
l=deep;
v=x;
}
for(int i=0;i<tree[x].size();i++){
int child=tree[x][i];
if(visit[child]) continue;
DFS(child,x,deep+1);
}
}
int main(){
int i,j;
while(cin>>n){
for(i=1;i<n;i++){
cin>>j;
tree[i+1].push_back(j);
tree[j].push_back(i+1);
}
memset(visit,0,sizeof(visit));
v=0;
l=0;
DFS(1,0,1);//此时的v(1)为树的最远点,长度l为根至v的长度
memset(visit,0,sizeof(visit));
l=0;
DFS(v,0,1);//此时的v(2)为离v(1)的最远点,长度l为v(1)至v(2)的长度
for(i=1;i<l/2;i++)
v=parent[v];
if(l%2) cout<<parent[v]<<endl;
else cout<<min(v,parent[v])<<" "<<max(v,parent[v])<<endl;
for(i=0;i<=n;i++) tree[i].clear();
}
return 0;
}
/*测试:
Sample Input
5
1
1
2
2
Sample Output
1 2
*/