UVA548 Tree
题意
给定一个点带权(权值各不相同,都是小于10000的正整数)的二叉树的中序和后序遍历,找一个叶子使得它到根的路径上权值最小。如果有多解,该叶子本身的权值尽 量小。
题解
首先在此回顾一下先序遍历、中序遍历、后序遍历的求法
PreOrder(T)=T的根节点+PreOrder(T的左子树)+PreOrder(T的右子树)
InOrder(T)=InOrder(T的左子树)+T的根节点+InOrder(T的右子树)
PostOrder(T)=PostOrder(T的左子树)+PostOrder(T的右子树)+T的根节点
我们不难发现可以利用后序遍历找到树根,再在中序遍历中找到树根,从而找出左右节点列表,然后递归构造左右子树
树造好了,剩下的也就不用说了
CODE
#include<bits/stdc++.h> #define N 10010 using namespace std; int ans,ansum,zx[N],hx[N],lc[N],rc[N],n; bool read(int* a) { string line; if(!getline(cin,line)) return false; stringstream ss(line); n=0;int x; while(ss>>x) a[n++]=x; return n>0; } int build(int l,int r,int L,int R) { if(l>r) return 0; int rt=hx[R]; int p=l; while(zx[p]!=rt) p++; int cnt=p-l; lc[rt]=build(l,p-1,L,L+cnt-1); rc[rt]=build(p+1,r,L+cnt,R-1); return rt; } void dfs(int u,int sum) { sum+=u; if(!lc[u]&&!rc[u]) if(sum<ansum || (sum==ansum&&u<ans)) ansum=sum,ans=u; if(lc[u]) dfs(lc[u],sum); if(rc[u]) dfs(rc[u],sum); } int main() { while(read(zx)) { read(hx); build(0,n-1,0,n-1); ansum=0x7fffffff; dfs(hx[n-1],0); printf("%d\n",ans); } return 0; }