标签:
题目大意:给出N个点,和每个点物品的售价,现在有一个商人,要从u点到v点,他想在路上多赚点钱。他可以从一个城市买物品,然后再卖到另一个城市,但买卖只允许一次,且不能回头走
问最多能赚多少
解题思路:果然智商捉急了。。
up数组纪录当前点到lca的最大利润
down数组纪录lca到当前点的最大利润
Max数组lca到当前点的最大值
Min纪录当前点到lca的最小值
这样的话,执行tarjan的时候,就可以更新一下这些值了
首先,答案的话肯定是max(max(up, down), Max - Min)
接着,怎么更新另外四个数组
(一下假设当前结点为u,祖先结点为v)
要更新up,应该要先更新距离lca近的祖先点,因为这样才不会重复
up[u] = max(up[u], max(up[v], Max[v] - Min[u]))
而更新down的话,也一样,也要先更新离lca近的祖先点
down[u] = max(down[u], max(down[v], Max[u] - Min[v]))
Min和Max的更新就比较简单了,就不详说了
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 50010
#define M 100010
struct Path{
int from, to, next;
}P[M];
struct Query{
int from, to, next;
}Q[M];
struct LCA{
int num, next;
}L[M];
int head_Path[N], head_Query[N], head_LCA[N], f[N];
int up[N], down[N], Min[N], Max[N], ans[N];
int tot, n, q;
bool vis[N];
void AddPdge_Path(int u, int v) {
P[tot].from = u; P[tot].to = v; P[tot].next = head_Path[u]; head_Path[u] = tot++;
u = u ^ v; v = u ^ v; u = u ^ v;
P[tot].from = u; P[tot].to = v; P[tot].next = head_Path[u]; head_Path[u] = tot++;
}
void AddPdge_Query(int u, int v) {
Q[tot].from = u; Q[tot].to = v; Q[tot].next = head_Query[u]; head_Query[u] = tot++;
u = u ^ v; v = u ^ v; u = u ^ v;
Q[tot].from = u; Q[tot].to = v; Q[tot].next = head_Query[u]; head_Query[u] = tot++;
}
void init() {
for (int i = 1; i <= n; i++) {
scanf("%d", &Min[i]);
Max[i] = Min[i];
up[i] = down[i] = 0;
}
int u, v;
memset(head_Path, -1, sizeof(head_Path));
tot = 0;
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
AddPdge_Path(u, v);
}
scanf("%d", &q);
memset(head_Query, -1, sizeof(head_Query));
tot = 0;
for (int i = 1; i <= q; i++) {
scanf("%d%d", &u, &v);
AddPdge_Query(u, v);
}
}
int update(int u) {
if (u == f[u])
return u;
int t = f[u];
f[u] = update(f[u]);
up[u] = max(up[u], max(up[t], Max[t] - Min[u]));
down[u] = max(down[u], max(down[t], Max[u] - Min[t]));
Min[u] = min(Min[u], Min[t]);
Max[u] = max(Max[u], Max[t]);
return f[u];
}
void AddEdge_LCA(int lca, int num) {
L[tot].num = num; L[tot].next = head_LCA[lca]; head_LCA[lca] = tot++;
}
void tarjan(int u) {
vis[u] = true; f[u] = u;
for (int i = head_Path[u]; ~i; i = P[i].next) {
int v = P[i].to;
if (!vis[v]) {
tarjan(v);
f[v] = u;
}
}
for (int i = head_Query[u]; ~i; i = Q[i].next) {
int v = Q[i].to;
if (vis[v]) {
int lca = update(v);
AddEdge_LCA(lca, i);
}
}
for (int i = head_LCA[u]; ~i; i = L[i].next) {
int t = L[i].num;
int u = Q[t].from;
int v = Q[t].to;
if (t & 1) {
t ^= 1;
u = u ^ v; v = u ^ v; u = u ^ v;
}
t /= 2;
update(u); update(v);
ans[t] = max(up[u], down[v]);
ans[t] = max(ans[t], Max[v] - Min[u]);
}
}
void solve() {
memset(vis, 0, sizeof(vis));
memset(ans, 0, sizeof(ans));
memset(head_LCA, -1, sizeof(head_LCA));
tot = 0;
tarjan(1);
for (int i = 0; i < q; i++)
printf("%d\n", ans[i]);
}
int main() {
while (scanf("%d", &n) != EOF) {
init();
solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
POJ - 3728 The merchant(dp+LCA)
标签:
原文地址:http://blog.csdn.net/l123012013048/article/details/47736973