中序遍历树(不一定是二叉树)

探讨了在一棵树上寻找字典序最小的中序遍历字符串的方法。通过枚举所有节点作为根节点进行中序遍历,并输出所有结果中字典序最小的字符串。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

给一棵树,你可以把其中任意一个节点作为根节点。每个节点都有一个小写字母,中序遍历,得到一个字符串,求所有能得到的字符串的字典序最小串。因为这棵树不一定是二叉树,所以中序遍历时,先中序遍历以节点序号最小的节点为根的子树,然后再遍历根节点,最后根据节点序号从小到大依次中序遍历剩下的子树。

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
根据题意,模拟书写递归函数。

首先不断递归到最左儿子,将最左儿子的字符加入ans字符串,接着回溯到父亲节点,判断刚才递归的是不是第一个儿子,如果是,就把父亲节点的字符加入ans。over。
伪代码如下
dfs(father)
    for son in father
        if(not visited)
            dfs(son)
        if(is the first son)
            add(father)
    if father have no son
    add father




#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <queue>
const int maxn = 1000005;
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
#define mem(a,x) memset(a,x,sizeof a)
char s[110];
vector<int>G[110];
string tmp;
int vis[110];
void traverse(int x){
    int isfirst =0;
    for(int i=0;i<G[x].size();i++){
        int nt = G[x][i];
        if(!vis[nt]){
            isfirst ++;
            vis[nt] = true;
            traverse(nt);
            if(isfirst == 1){
                tmp += s[x];
            }
        }
    }
    if(!isfirst)
        tmp += s[x];
}
int main(){
    int n;
    while(scanf("%d",&n) !=EOF){
        scanf("%s",s);
        for(int i=0;i<=n;i++) G[i].clear();
        for(int i=0;i<n-1;i++){
            int a,b;scanf("%d%d",&a,&b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        vector<string>vt;
        for(int i=0;i<n;i++){
            tmp = "";
            mem(vis,0);
            vis[i] = true;
            traverse(i);
            vt.push_back(tmp);
        }
        sort(vt.begin(),vt.end());
        cout<<vt[0]<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值