题目链接:http://poj.org/problem?id=3728

思路:题目的意思是求树上a -> b的路径上的最大收益(在最小值买入,在最大值卖出)。

我们假设路径a - > b 之间的LCA(a, b) = f, 并且另up[a]表示a - > f之间的最大收益,down[a]表示f - > a之间的最大收益,dp_max[a]表示a - > f之间的最大值,dp_min[a]表示a - > f之间的最小值,于是可以得出关系: ans[id] = max(max(up[a], down[b]), dp_max[b] - dp_min[a])。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAX_N = (50000 + 5000);
const int MAX_M = (MAX_N << 2);
const int inf = 0x3f3f3f3f;
int NE1, NE2, NE3, head1[MAX_N], head2[MAX_N], head3[MAX_N]; void Init()
{
NE1 = NE2 = NE3 = 0;
memset(head1, -1, sizeof(head1));
memset(head2, -1, sizeof(head2));
memset(head3, -1, sizeof(head3)); } int N, Q, ans[MAX_N], value[MAX_N], vis[MAX_N]; struct Edge1 {
int v, next;
} edge1[MAX_M]; void Insert1(int u, int v)
{
edge1[NE1].v = v;
edge1[NE1].next = head1[u];
head1[u] = NE1++;
} struct Edge {
int v, id, next;
} edge2[MAX_M], edge3[MAX_M]; void Insert2(int u, int v, int id, int flag)
{
if (!flag) {
edge2[NE2].v = v;
edge2[NE2].id = id;
edge2[NE2].next = head2[u];
head2[u] = NE2++;
} else {
edge3[NE3].v = v;
edge3[NE3].id = id;
edge3[NE3].next = head3[u];
head3[u] = NE3++;
}
} int parent[MAX_N];
int up[MAX_N], down[MAX_N], dp_max[MAX_N], dp_min[MAX_N]; int find(int x)
{
if (x == parent[x]) {
return x;
} int fa = parent[x];
parent[x] = find(parent[x]); up[x] = max(max(up[x], up[fa]), dp_max[fa] - dp_min[x]);
down[x] = max(max(down[x], down[fa]), dp_max[x] - dp_min[fa]);
dp_max[x] = max(dp_max[x], dp_max[fa]);
dp_min[x] = min(dp_min[x], dp_min[fa]); return parent[x];
} struct Node {
int u, v;
} node[MAX_N]; void Tarjan(int u)
{
vis[u] = 1;
parent[u] = u;
//Q;
for (int i = head2[u]; ~i; i = edge2[i].next) {
int v = edge2[i].v, id = edge2[i].id;
if (!vis[v]) continue;
int fa = find(v);
Insert2(fa, v, id, 1);
} for (int i = head1[u]; ~i; i = edge1[i].next) {
int v = edge1[i].v;
if (vis[v]) continue;
Tarjan(v);
parent[v] = u;
} //edge3
for (int i = head3[u]; ~i; i = edge3[i].next) {
int id = edge3[i].id;
find(node[id].u);
find(node[id].v);
ans[id] = max(max(up[node[id].u], down[node[id].v]), dp_max[node[id].v] - dp_min[node[id].u]);
}
} int main()
{
while (~scanf("%d", &N)) {
for (int i = 1; i <= N; ++i) {
scanf("%d", &value[i]);
up[i] = down[i] = 0;
dp_max[i] = dp_min[i] = value[i];
} Init(); for (int i = 1; i < N; ++i) {
int u, v;
scanf("%d %d", &u, &v);
Insert1(u, v);
Insert1(v, u);
} scanf("%d", &Q);
for (int i = 1; i <= Q; ++i) {
scanf("%d %d", &node[i].u, &node[i].v);
Insert2(node[i].u, node[i].v, i, 0);
Insert2(node[i].v, node[i].u, i, 0);
} memset(vis, 0, sizeof(vis));
Tarjan(1); for (int i = 1; i <= Q; ++i) printf("%d\n", ans[i]);
}
return 0;
}



poj 3728(LCA + dp)的更多相关文章

  1. Fire (poj 2152 树形dp)

    Fire (poj 2152 树形dp) 给定一棵n个结点的树(1<n<=1000).现在要选择某些点,使得整棵树都被覆盖到.当选择第i个点的时候,可以覆盖和它距离在d[i]之内的结点,同 ...

  2. POJ 3728 The merchant(LCA+DP)

    The merchant Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total ...

  3. poj 3728 The merchant 倍增lca求dp

    题目: zdf给出的题目翻译: 从前有一个富饶的国度,在这里人们可以进行自由的交易.这个国度形成一个n个点的无向图,每个点表示一个城市,并且有一个权值w[i],表示这个城市出售或收购这个权值的物品.又 ...

  4. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

  5. 【题解】POJ 3417 Network(倍增求LCA+DP+树上差分)

    POJ3417:http://poj.org/problem?id=3417 思路 我们注意到由“主要边”构成一颗树 “附加边”则是非树边 把一条附加边(x,y)加入树中 会与树上x,y之间构成一个环 ...

  6. poj 3417 树形dp+LCA

    思路:我以前一直喜欢用根号n分段的LCA.在这题上挂了,第一次发现这样的LCA被卡.果断改用Tarjan离线算法求LCA. 当前节点为u,其子节点为v.那么: 当以v根的子树中含有连接子树以外点的边数 ...

  7. poj 3728 The merchant(LCA)

    Description There are N cities in a country, and there is one and only one simple path between each ...

  8. POJ 3278:The merchant(LCA&DP)

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6864   Accepted: 2375 Desc ...

  9. POJ 3728 The merchant(并查集+DFS)

    [题目链接] http://poj.org/problem?id=3728 [题目大意] 给出一棵树,每个点上都可以交易货物,现在给出某货物在不同点的价格, 问从u到v的路程中,只允许做一次买入和一次 ...

随机推荐

  1. 了解了下 Google 最新的 Fuchsia OS

    就是看到篇报道,有点好奇,就去FQ挖了点东西回来. 我似乎已开始就抓到了重点,没错,就是 LK . LK 是 Travis Geiselbrecht 写的一个针对 ARM 的嵌入式操作系统,开源的.点 ...

  2. php多文件压缩下载

    /*php多文件压缩并且下载*/ function addFileToZip($path,$zip){ $handler=opendir($path); //打开当前文件夹由$path指定. whil ...

  3. Redis中持久化的两种方法详解

    Redis提供了两种不同的持久化方法来将数据存储到硬盘里面.一种方法叫快照(snapshotting),它可以将存在于某一时刻的所有数据都写入硬盘里;另一种方法教只追加文件(append-only f ...

  4. dos 固定ip命令

    dos 固定ip命令 ***************************************************************************************** ...

  5. centos 下测试网速

    wget https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py chmod a+rx speedtest. ...

  6. MapReduce的ReduceTask任务的运行源码级分析

    MapReduce的MapTask任务的运行源码级分析 这篇文章好不容易恢复了...谢天谢地...这篇文章讲了MapTask的执行流程.咱们这一节讲解ReduceTask的执行流程.ReduceTas ...

  7. 修改mysql默认字符编码出现的Job failed to start解决方法

    5.5以后的版本对字符编码方式修改的办法,原来在[mysqld]下的修改已经发生了变化,正确方式如下: [mysqld]下添加的应该为: character-set-server=utf8 colla ...

  8. jquery.SuperSlide.js只需要调用一个插件就能实现网页大部分特效--推荐

    很棒的一个插件,http://www.superslide2.com/

  9. sdcms标签

    模板防盗:<%if not in_sdcms then response.write("template load fail"):response.end() end if% ...

  10. opencv二值化处理

    #include "stdafx.h"//对一张图片进行二值化处理 IplImage *pSrclmg =NULL;//载入的图片IplImage *pDeclmg =NULL;/ ...