uva548 树
你的任务是找出一棵二元树中最小路径上终端节点(树叶,leaf node)的值。 所谓路径乃指从根节点(root)旅行到任一终端节点。 路径的值为所经过的节点的值的和(包含根节点及终端节点)。 而最小路径就是指路径值最小的那条。
Input。
每组测试数据2列,用来描述一棵二元树。 第一列的序列为以中序旅行(inorder traversal)所经过的节点的值。 第二列的序列为以后序旅行(postorder traversal)所经过的节点的值。
各列中所有的值都是整数(大于0,小于10000),且值都不同。 你可以假设二元树的节点数最多10000,最少1。 输入列的长度最长不会超过1000000。
Output。
对每组测试数据,请输出二元树中最小路径上终端节点的值。 如果有不止一条最小路径,请输出终端节点值最小的值。
Sample Input。
3 2 1 4 5 7 6 3 1 2 5 6 7 4 7 8 11 3 5 16 12 18 8 3 11 7 16 18 12 5 255 255
Sample Output。
1 3 255
翻译来源于http://luckycat.kshs.kh.edu.tw/
题目大意为给出中序和后序遍历顺序,求从跟开始的最短路节点。实际上这道题的核心问题仍旧是建树后dfs求解,dfs过程十分简洁,只需要按顺序进入到种子节点,判断是否需要更新最大值即
可。关键在于给出中序和后序遍历后要面对的建树问题。由于后序遍历的最后一个位置是根节点的位置,我们找出他在中序遍历后的位置,就可以把一颗树分为完整的2棵树,通过传参,给出新的
两棵树的中序和后序节点,表示根的位置就可以完成一个递归建树的过程。过程中有一些细节需要注意,并且还需要注意输入过程中我们使用了 stringstream tf(s);//字符流转换数字和字
符 来方便题目数据的输入
#include<bits/stdc++.h> using namespace std; struct Node{ int v; Node *left,*right; };//首先利用结构体构造树的节点 Node *root;//申请根节点 Node *newnode() {return new Node();}//添加新的节点 const int inf=0x7fffffff;//设定值最大 const int maxn=10000+10; int p[maxn],i[maxn],n,ok,b,best; bool read(int *a)//读入数据,进行存储 { string s; if(!getline(cin,s)) return false;//输入进树的节点数 stringstream tf(s);//字符流转换数字和字符 int x; n=0; while(tf>>x) a[n++]=x; return n>0; } Node* bulid(int l1,int r1,int l2,int r2)//l1 r1中序位置 l2 r2后序位置 { if(l1>r1) return NULL;//null==空,所以空数返回空 Node *t=newnode();//申请节点 t->v=p[r2];//运用链表 int p=l1; while(i[p]!=t->v) p++;//添加子树 int cnt=p-l1;//p为分解点的值, t->left=bulid(l1,p-1,l2,l2+cnt-1); t->right=bulid(p+1,r1,l2+cnt,r2-1);//构造左右子树 因为左树和右数的值在第一次后序遍历中分别是中值的前一个和倒数第二位 return t; } void dfs(Node *t,int sum)//用深搜寻找最小值的终端叶子 { sum+=t->v; if(!t->left&&!t->right){//如果当前时种子节点,尝试更新。 if(sum<b||(sum==b&&t->v<best)){ b=sum;best=t->v; } } if(t->left) dfs(t->left,sum); if(t->right) dfs(t->right,sum);//搜索回溯 } int main() { while(read(i)){//输入 read(p); b=inf;best=inf; root=bulid(0,n-1,0,n-1); dfs(root,0);//从根节点开始搜 printf("%d\n",best); } }

浙公网安备 33010602011771号