版权声明:本文纯属作者口胡,欢迎转载 https://blog.csdn.net/TQCAI666/article/details/86758706
https://vpn.bupt.edu.cn/http/10.105.242.80/problem/p/109/
不难的一题,但写了贼久。。。
题设中序遍历步骤:
- 中序遍历(第
1
个子节点) - 访问根节点
- 中序遍历(第
2...N
子节点)
看起来很简单,但是遇到了以下坑。
- 必须要设置访问标记,否则直接访问父结点形成死循环
- 必须首先置根结点已访问
(A)
- 要对子节点向量进行排序
- 对于寻找第一棵左子树,必须要参照
(B)
进行循环,而不能简单的访问g[r][0]
- 对于寻找根结点的遍历中,每次使用中序遍历之前,要对vis进行初始化
(C)
写了半天连样例都过不了… …要引起重视了
AC代码
#include <bits/stdc++.h>
#define FF(a,b) for(int a=0;a<b;a++)
#define F(a,b) for(int a=1;a<=b;a++)
#define LEN 100
#define INF 1000000
#define bug(x) cout<<#x<<"="<<x<<endl;
using namespace std;
typedef long long ll;
const double pi=acos(-1);
vector<int> g[110];
int N;
string seq;
char s[110];
int vis[110];
int visit(int r){
seq+=s[r];
vis[r]=1;
}
void inorder(int r){
if(vis[r]) return;
vis[r]=1; //必须首先置根结点已访问(A)
if(g[r].size()){
sort(g[r].begin(),g[r].end());
int sz=g[r].size();
int i,to;
for(i=0;i<sz;i++){ //找到左子树(B)
to=g[r][i];
if(vis[to]) continue;
break;
}
if(i==sz) visit(r);
else{
inorder(to);//左子树
visit(r);
for(i++;i<sz;i++)
inorder(g[r][i]);
}
}else{
visit(r);
}
}
void inorder_travel(int r){
memset(vis,0,sizeof vis); //(C)
seq="";inorder(r);
}
int main()
{
// freopen("./in","r",stdin);
int a,b;
while(scanf("%d",&N)>0){
scanf("%s",s);
FF(i,N) g[i].clear();
memset(vis,0,sizeof vis);
FF(i,N-1){
scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
inorder_travel(0);
string minSeq=seq;
for(int i=1;i<N;i++){
inorder_travel(i);
if(seq.length()!=N) continue;
if(seq<minSeq){
minSeq=seq;
}
}
printf("%s\n",minSeq.c_str());
}
return 0;
}