题目
BUPT 2011 网研 ProblemC(oj)
给一棵树,你可以把其中任意一个节点作为根节点。每个节点都有一个小写字母,中序遍历,得到一个字符串,求所有能得到的字符串的字典序最小串。因为这棵树不一定是二叉树,所以中序遍历时,先中序遍历以节点序号最小的节点为根的子树,然后再遍历根节点,最后根据节点序号从小到大依次中序遍历剩下的
子树。
输入描述
多组数据,以 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
HINT
意思就是请枚举所有的点为根,然后中序遍历
最后输出所有结果中字典序最小的
比如说第二组数据
以 0 为根时结果为 bacd
以 1 为根时结果为 cadb
以 2 为根时结果为 badc
以 3 为根时结果为 bacd
所以字典序最小的是 bacd
题解
对于多叉树的中序遍历采用DFS,将各节点依次作为根进行中序遍历,找出最小的中序遍历序列
#include <bits/stdc++.h>
using namespace std;
int edge[105][105];//邻接矩阵
int visited[105];
string s,res,tmp;//tmp是每次从一个节点dfs遍历得到的字符串,如果小于result,则代替它
void dfs(int pos,int n)
{
visited[pos]=1;
vector<int>neighbor;
for(int i=0;i<n;i++)
{
if(i==pos)
continue;
if(!visited[i]&&edge[pos][i])
neighbor.push_back(i);//未被访问的邻接节点加入neighbor
}
if(neighbor.size()>0)
{
dfs(neighbor[0],n);//左子树
tmp+=s[pos];//左子树加入后,加入节点字符
for(int i=1;i<neighbor.size();i++)//右子树
dfs(neighbor[i],n);
}
else
tmp+=s[pos];
}
int main()
{
int n;
while(cin>>n)
{
cin>>s;
memset(edge,0,sizeof(edge));//注意清空邻接矩阵
for(int i=0;i<n-1;i++)
{
int a,b;
cin>>a>>b;
edge[a][b]=1;
edge[b][a]=1;
}
for(int i=0;i<n;i++)
{
memset(visited,0,sizeof(visited));//新的根节点,重置visited数组
tmp="";
dfs(i,n);
if(i==0)
res=tmp;
else if(tmp<res)
res=tmp;
}
cout<<res<<endl;
}
}