poj3728 The merchant
来源:互联网 发布:java el表达式 编辑:程序博客网 时间:2024/04/29 15:27
Description
There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and wants to earn as much money as possible in each path. When he move along a path, he can choose one city to buy some goods and sell them in a city after it. The goods in all cities are the same but the prices are different. Now your task is to calculate the maximum possible profit on each path.
Input
The first line contains N, the number of cities.
Each of the next N lines contains wi the goods' price in each city.
Each of the next N-1 lines contains labels of two cities, describing a road between the two cities.
The next line contains Q, the number of paths.
Each of the next Q lines contains labels of two cities, describing a path. The cities are numbered from 1 to N.
1 ≤ N, wi, Q ≤ 50000
Output
The output contains Q lines, each contains the maximum profit of the corresponding path. If no positive profit can be earned, output 0 instead.
Sample Input
41 5 3 21 33 23 491 21 31 42 32 12 43 13 23 4
Sample Output
422000020
这题花了很长时间啊..想明白后发现对离线tarjan算法的理解更深了,tarjan的算法核心是先处理较深的子树,然后再处理较浅的子树。这道题也是一样,因为样例很多,所以普通的暴力方法不行,这里就要结合taijan的特点,先把询问的问题分类,然后遍历到某个节点,就把最近公共祖先为这个节点的所有问题都处理完,然后再求这个节点父节点的问题。
因为获得价值最大只有三种情况,设f为u,v的最近公共祖先,一种是起点u到f的最大区间值,一种是f到终点v的最大区间值,还有就是f到v经过的最大值减去u到f经过的最小值。所以要记录4个变量:
up[u]表示u->f的最大maxval
down[u]表示f->u的最大maxval
maxw[u]表示u-f的最大w[i]
minw[u]表示u-f的最小w[i]
然后在并查集压缩路径的时候更新。
#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<vector>#include<map>#include<set>#include<queue>#include<stack>#include<string>#include<algorithm>using namespace std;typedef long long ll;#define inf 0x7fffffff#define maxn 50050int first[maxn],pre[maxn],vis[maxn],w[maxn],uu[maxn],vv[maxn];struct node{ int to,next;}e[2*maxn];int h[maxn];struct node1{ int to,next,idx;}question[2*maxn];int h1[maxn];struct node2{ int next,idx;}question1[2*maxn];int answer[2*maxn];int maxw[maxn],minw[maxn],up[maxn],down[maxn];int tot;int findx(int x){ //这里要用递归写法 int i,j=x,r=x; if(pre[x]==x){ return x; } int fa=pre[x]; pre[x]=findx(fa); up[x]=max(max(up[fa],up[x]),maxw[fa]-minw[x]); //这里上面两个与下面两个位置不能换 down[x]=max(max(down[fa],down[x]),maxw[x]-minw[fa]); minw[x]=min(minw[x],minw[fa]); maxw[x]=max(maxw[x],maxw[fa]); return pre[x];}void lca(int u){ int i,j,x,y,v,idx; vis[u]=1; for(i=h[u];i!=-1;i=question[i].next){ //对问题进行分类,把祖先同为f的放在一起解决,这样递归上来的时候就会解决了 v=question[i].to; idx=question[i].idx; if(!vis[v])continue; int f=findx(v); tot++; question1[tot].next=h1[f];question1[tot].idx=idx; h1[f]=tot; } for(i=first[u];i!=-1;i=e[i].next){ int v=e[i].to; if(vis[v])continue; lca(v); pre[v]=u; findx(v); } for(i=h1[u];i!=-1;i=question1[i].next){ idx=question1[i].idx; findx(uu[idx]); findx(vv[idx]); int t=max(up[uu[idx] ],down[vv[idx] ]); answer[question1[i].idx ]=max(t,maxw[vv[idx] ]-minw[uu[idx] ]); }}int main(){ int n,m,i,j,tot,q,c,d; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++){ scanf("%d",&w[i]); maxw[i]=minw[i]=w[i]; up[i]=down[i]=0; pre[i]=i; } tot=0; memset(first,-1,sizeof(first)); for(i=1;i<=n-1;i++){ scanf("%d%d",&c,&d); e[i].next=first[c];e[i].to=d; first[c]=i; e[i+n-1].next=first[d];e[i+n-1].to=c; first[d]=i+n-1; } memset(h,-1,sizeof(h)); scanf("%d",&q); for(i=1;i<=q;i++){ scanf("%d%d",&uu[i],&vv[i]); int c=uu[i]; int d=vv[i]; question[i].to=d;question[i].idx=i;question[i].next=h[c]; h[c]=i; question[i+q].to=c;question[i+q].idx=i;question[i+q].next=h[d]; h[d]=i+q; } memset(vis,0,sizeof(vis)); memset(h1,-1,sizeof(h1)); tot=0; lca(1); for(i=1;i<=q;i++){ printf("%d\n",answer[i]); } } return 0;}
- poj3728 The merchant
- poj3728 The merchant
- 【POJ3728】The merchant
- poj3728 The merchant 倍增LCA
- LCA 练习题:【POJ3728】The merchant
- poj3728 The merchant LCA+并查集
- poj3728 The merchant LCA(带权并查集?)
- poj3728 The merchant LCA+RMQ或 LCA+b并查集 好题!
- POJ 3728 The merchant
- poj 3728 The merchant
- POJ 3728 The merchant
- POJ-3728-The merchant
- POJ 3728 【The merchant】
- POJ 3728 The merchant
- POJ 3728 The merchant
- The merchant POJ
- poj 3728 The merchant
- POJ 3728 The merchant
- linux0.99网络模块-传输层(UDP接收)
- iOS开发之c语言基础-动态内存分配与管理
- Web开发人员常犯的10个错误
- 安装scikit-learn win7 64位
- 2015 中国大学生程序设计竞赛解题报告
- poj3728 The merchant
- 每天被面试虐一点点(一)
- 基于对话框的API串口软件开发
- Eclipse中文注释乱码解决
- JVM内存参数
- iOS开发之c语言基础-动态内存分配与管理题目
- VS2015 - WP8.1 app project with Microsoft VCLibs reference problem
- 杂六笔记
- Redis在Windows下安装和PHP中使用