题目描述
给一棵树,你可以把其中任意一个节点作为根节点。每个节点都有一个小写字母,中序遍历,得到一个字符串,求所有能得到的字符串的字典序最小串。因为这棵树不一定是二叉树,所以中序遍历时,先中序遍历以节点序号最小的节点为根的子树,然后再遍历根节点,最后根据节点序号从小到大依次中序遍历剩下的子树。
HINT
意思就是请枚举所有的点为根,然后中序遍历
最后输出所有结果中字典序最小的
比如说第二组数据
以0为根时结果为 bacd
以1为根时结果为 cadb
以2为根时结果为 badc
以3为根时结果为 bacd
所以字典序最小的是bacd
输入格式
多组数据,以EOF结束。
第一行一个数n(0< n < =100),表示树的节点的个数,节点从0开始。
然后一个长度为n的串,第i(0< = i < n)个字符表示节点i的字符。
接下来n-1行,每行两个数a,b,(0< = a,b < n),表示a和b之间有一条无向边。
输出格式
题中要求的最小的字符串
输入样例
3
bac
0 1
1 2
4
abcd
0 1
0 2
0 3
输出样例
bac
bacd
#include <bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn = 110;
int vis[maxn];
int mp[maxn][maxn];
string tmp="";
int n;
char s[maxn];
void dfs(int x)
{
vis[x] = 1;
if(tmp.size() == n)//递归出口
return;
int i;
for(i = 0; i<n; i++)//左子树
{
if(!vis[i] && mp[x][i])
{
dfs(i);
break;
}
}
tmp+=s[x];//根节点
//cout<<tmp<<endl;
for(;i < n; i++)//右子树
{
if(!vis[i] && mp[x][i])
{
dfs(i);
}
}
}
int main()
{
while(~scanf("%d", &n))
{
scanf("%s",s);
memset(mp,0,sizeof(mp));
for(int i = 1; i < n; i++)
{
int a, b;
scanf("%d%d", &a, &b);
mp[a][b] = mp[b][a] = 1;
}
string res = "zzzzzzzzzzzzz";
for(int i = 0; i < n; i++)
{
tmp = "";
memset(vis, 0, sizeof(vis));
dfs(i);
if(res > tmp)
res = tmp;
// cout<<"I am :"<<tmp<<endl;
// getchar();
}
cout<<res<<endl;
}
return 0;
}