Codeforces 29D Ant on the Tree 树的遍历 dfs序
题目链接:点击打开链接
题意:
给定n个节点的树
1为根
则此时叶子节点已经确定
最后一行给出叶子节点的顺序
目标:
遍历树并输出路径。要求遍历叶子节点时依照给定叶子节点的先后顺序訪问。
思路:
给每一个节点加一个优先级。
把最后一个叶子节点到父节点的路径上的点优先级改为1
把倒数第二个叶子节点到父节点的路径上的点优先级改为2
如此每一个点就有一个优先级,每一个訪问儿子节点时先訪问优先级大的就可以
对于无解的推断:得到的欧拉序列不满足输入的叶子节点顺序即是无解。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set> #include <vector> #include <map> using namespace std; #define ll int #define N 310 ll n; vector<ll>G[N]; int fa[N], du[N]; void dfs(int u,int father){ fa[u] = father; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(v==father)continue; dfs(v,u); } } int val[N], Stack[N<<1], top; bool cmp(int a,int b) { return val[a]>val[b]; } void work(int u, int father) { Stack[top++] = u; vector<int>son; son.clear(); for(int i = 0; i < G[u].size(); i++){ int v = G[u][i]; if(v==father)continue; son.push_back(v); } sort(son.begin(), son.end(), cmp); for(int i = 0; i < son.size(); i++) { work(son[i], u); Stack[top++] = u; } } vector<int>input; bool ok(){ int u = 0; for(int i = 0; i < top; i++) if(Stack[i]==input[u]) u++; return u >= input.size(); } int main(){ ll i,j,u,v; while(cin>>n){ input.clear(); memset(du, 0, sizeof du); for(i = 1; i <= n; i++) G[i].clear(); for(i = 1; i < n; i++) { scanf("%d %d",&u,&v); G[u].push_back(v); G[v].push_back(u); du[u]++; du[v]++; } int leaf = 0; for(i = 2; i <= n; i++) if(du[i]==1) leaf++; dfs(1,-1); for(i = leaf; i; i--) { scanf("%d",&u); input.push_back(u); while(u!=-1){ val[u] = i; u = fa[u]; } } top = 0; work(1,-1); if(ok()) { <span style="white-space:pre"> </span>for(i = 0; i < top; i++) printf("%d%c",Stack[i],i==top-1?'\n':' '); } else puts("-1"); } return 0; }