赞
踩
给一棵树,你可以把其中任意一个节点作为根节点。每个节点都有一个小写字母,中序遍历,得到一个字符串,求所有能得到的字符串的字典序最小串。因为这棵树不一定是二叉树,所以中序遍历时,先中序遍历以节点序号最小的节点为根的子树,然后再遍历根节点,最后根据节点序号从小到大依次中序遍历剩下的子树。
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
- 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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。