题意:
给定前序遍历和中序遍历,问u和v的lca (先是中序,后是中序)
题解:
方法一:
参考题解 将树映射到一颗BST上,在BST上找到答案然后再映射回原本的树 方法二: 参考题解 已知某个树的根结点,若a和b在根结点的左边,则a和b的最近公共祖先在当前子树根结点的左子树寻找,如果a和b在当前子树根结点的两边,在当前子树的根结点就是a和b的最近公共祖先,如果a和b在当前子树根结点的右边,则a和b的最近公共祖先就在当前子树的右子树寻找。中序加先序可以唯一确定一棵树,在不构建树的情况下,在每一层的递归中,可以得到树的根结点,在此时并入lca算法可以确定两个结点的公共祖先~
代码:
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std
;
int m
, n
;
int opre
[10009], oin
[10009];
int pre
[10009], in
[10009];
map
<int, int> otos
, stoo
;
int main()
{
cin
>> m
>> n
;
for (int i
= 0; i
< n
; i
++)
{
cin
>> oin
[i
];
otos
[oin
[i
]] = i
;
stoo
[i
] = oin
[i
];
}
for (int i
= 0; i
< n
; i
++)
{
cin
>> opre
[i
];
pre
[i
] = otos
[opre
[i
]];
}
for (int i
= 0; i
< m
; i
++)
{
int u
, v
;
int a
;
bool flag1
= true
, flag2
= true
;
cin
>> u
>> v
;
if (otos
.find(u
) == otos
.end())
flag1
= false
;
if (otos
.find(v
) == otos
.end())
flag2
= false
;
if (!flag1
|| !flag2
)
{
if (!flag1
&& !flag2
)
printf("ERROR: %d and %d are not found.\n", u
, v
);
else
printf("ERROR: %d is not found.\n", flag1
== false
? u
: v
);
continue;
}
u
= otos
[u
];
v
= otos
[v
];
for (int j
= 0; j
< n
; j
++)
{
a
= pre
[j
];
if (a
> u
&& a
< v
|| a
< u
&& a
> v
|| a
== u
|| a
== v
)
break;
}
u
= stoo
[u
];
v
= stoo
[v
];
a
= stoo
[a
];
if (a
== u
|| a
== v
)
printf("%d is an ancestor of %d.\n", a
, a
== u
? v
: u
);
else
printf("LCA of %d and %d is %d.\n", u
, v
, a
);
}
return 0;
}
#include <iostream>
#include <vector>
#include <map>
using namespace std
;
map
<int, int> pos
;
vector
<int> in
, pre
;
void lca(int inl
, int inr
, int preRoot
, int a
, int b
) {
if (inl
> inr
) return;
int inRoot
= pos
[pre
[preRoot
]], aIn
= pos
[a
], bIn
= pos
[b
];
if (aIn
< inRoot
&& bIn
< inRoot
)
lca(inl
, inRoot
-1, preRoot
+1, a
, b
);
else if ((aIn
< inRoot
&& bIn
> inRoot
) || (aIn
> inRoot
&& bIn
< inRoot
))
printf("LCA of %d and %d is %d.\n", a
, b
, in
[inRoot
]);
else if (aIn
> inRoot
&& bIn
> inRoot
)
lca(inRoot
+1, inr
, preRoot
+1+(inRoot
-inl
), a
, b
);
else if (aIn
== inRoot
)
printf("%d is an ancestor of %d.\n", a
, b
);
else if (bIn
== inRoot
)
printf("%d is an ancestor of %d.\n", b
, a
);
}
int main() {
int m
, n
, a
, b
;
scanf("%d %d", &m
, &n
);
in
.resize(n
+ 1), pre
.resize(n
+ 1);
for (int i
= 1; i
<= n
; i
++) {
scanf("%d", &in
[i
]);
pos
[in
[i
]] = i
;
}
for (int i
= 1; i
<= n
; i
++) scanf("%d", &pre
[i
]);
for (int i
= 0; i
< m
; i
++) {
scanf("%d %d", &a
, &b
);
if (pos
[a
] == 0 && pos
[b
] == 0)
printf("ERROR: %d and %d are not found.\n", a
, b
);
else if (pos
[a
] == 0 || pos
[b
] == 0)
printf("ERROR: %d is not found.\n", pos
[a
] == 0 ? a
: b
);
else
lca(1, n
, 1, a
, b
);
}
return 0;
}