UVA_548
直观的思路就是先把树建出来,然后再dfs,后来看了别人的解题报告之后发现其实可以不用建树的,因为建树的过程本身也是遍历树的一个过程,这样直接把该求的求出来就好了。
建树的核心思想是一棵子树后序遍历的最后一个值一定是根节点,这样再在中序遍历中找到根节点之后,就可以把这棵子树分成根节点、左子树、右子树这三部分了,继续按这个思想处理左右两棵子树即可完成建树的过程。
#include<stdio.h>
#include<string.h>
#define MAXD 10010
#define INF 0x3f3f3f3f
int N, min, minv, value[MAXD], left[MAXD], right[MAXD], size, inorder[MAXD], postorder[MAXD];
void build(int fa, int flag, int x1, int y1, int x2, int y2)
{
int i, j, k;
++ size;
k = size;
value[k] = postorder[y2];
if(flag)
right[fa] = k;
else
left[fa] = k;
for(i = x1; inorder[i] != postorder[y2]; i ++);
if(i > x1)
build(k, 0, x1, i - 1, x2, x2 + i - 1 - x1);
if(i < y1)
build(k, 1, i + 1, y1, i + y2 - y1, y2 - 1);
}
void dfs(int x, int res)
{
res += value[x];
if(left[x] != -1)
dfs(left[x], res);
if(right[x] != -1)
dfs(right[x], res);
if(left[x] == -1 && right[x] == -1)
{
if(res < min)
{
min = res;
minv = value[x];
}
else if(res == min && value[x] < minv)
minv = value[x];
}
}
void solve()
{
int i, j, k;
memset(left, -1, sizeof(left));
memset(right, -1, sizeof(right));
size = 0;
build(0, 0, 0, N - 1, 0, N - 1);
min = INF;
dfs(1, 0);
printf("%d\n", minv);
}
int main()
{
char ch;
N = 0;
while(scanf("%d%c", &inorder[N ++], &ch) == 2)
{
if(ch == '\n')
{
for(int i = 0; i < N; i ++)
scanf("%d", &postorder[i]);
solve();
N = 0;
}
}
return 0;
}