某个国家有N个城市,编号0 至 N-1,他们之间用N - 1条道路连接,道路是双向行驶的,沿着道路你可以到达任何一个城市。你有一个旅行计划,这个计划是从编号K的城市出发,每天到达一个你没有去过的城市,并且旅途中经过的没有去过的城市尽可能的多(如果有2条路线,经过的没有去过的城市同样多,优先考虑编号最小的城市),直到所有城市都观光过一遍。现在给出城市之间的交通图T,以及出发地点K,你来设计一个旅行计划,满足上面的条件。例如:
(K = 2)

第1天 从2到0 (城市 1 和 0 变成去过的)
第2天 从0到6 (城市 4 和 6 变成去过的)
第3天 从6到3 (城市 3 变成去过的)
第4天 从3到5 (城市 5 变成去过的)
上图的输入数据为:0 1 2 2 1 4。共7个节点,除节点0之外,共6行数据。
第1个数0表示1到0有1条道路。
第2个数1表示2到1有1条道路。
Input
第1行:2个数N,K(1 <= N <= 50000, 0 <= K <= N - 1) 第2 - N + 1行:每行一个数,表示节点之间的道路。
Output
输出旅行的路线图,即每天到达的城市编号。
Input示例
7 2 0 1 2 2 1 4
Output示例
2 0 6 3 5
解:很明显目标城市一定是叶子节点,关键是怎么实现;
一开始按照题目条件一步一步模拟,结果中间环节处理的很复杂;如果按照宏观的角度来考虑的话节点深度大的 节点编号小的一定先处理(不会被影响) 倒着遍历一遍 他的节点数量就是没被访问过的节点数量
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;
const int N = 50000+10;
typedef long long LL;
vector<int>p[N];
int fax[N], vis[N];
struct node
{
int x, cnt, minx;
bool operator <(const node &A)const
{
if(cnt!=A.cnt) return cnt>A.cnt;
else return minx<A.minx;
}
}q[N];
set<node>st;
set<node>::iterator it;
void dfs(int u,int fa,int sum)
{
fax[u]=fa;
if(p[u].size()==1&&fa!=-1)
{
node tmp;
tmp.cnt=sum,tmp.x=u,tmp.minx=u;
st.insert(tmp);
return ;
}
for(int i=0;i<p[u].size();i++)
{
int v=p[u][i];
if(v==fa) continue;
dfs(v,u,sum+1);
}
return ;
}
int k, root;
int main()
{
int n;
scanf("%d %d", &n, &k);
for(int i=1;i<n;i++)
{
int x;
scanf("%d", &x);
p[x].push_back(i),p[i].push_back(x);
}
dfs(k,-1,1);
printf("%d\n",k);
memset(vis,0,sizeof(vis));
int cnt1=0;
for(it=st.begin();it!=st.end();it++)
{
int u=(*it).x, num=0;
while(u!=-1&&u!=k)
{
if(!vis[u]) vis[u]=1,u=fax[u],num++;
else break;
}
q[cnt1].x=(*it).x,q[cnt1].minx=(*it).x,q[cnt1].cnt=num;
cnt1++;
}
sort(q,q+cnt1);
for(int i=0;i<cnt1;i++) printf("%d\n",q[i].x);
return 0;
}