poj 3728 The merchant(tarjan求lca)
来源:互联网 发布:淘宝推广多少钱 编辑:程序博客网 时间:2024/05/22 03:38
题意:给出一个n个节点的树,树上的每个节点都有某个价值的货物,有q次询问,每次询问从u到v的路径上能获得的最大利润(只买一次卖一次)
思路:最开始以为从u到v和从v到u都行,结果样例都过不了……其实可以考虑下uv顺序无关的情况,这种情况下,我们只要知道这条路径中货物价值的最大值和最小值,然后把它们相减就能得到答案了,如果这么对于每个节点我们知道知道三个值就能在用并查集合并的时候解决了:从u到当前根节点的最大值和最小值,从u到当前根节点的最大利润。另外,由于到达v点时,v还没有合并到当前根节点,所以在此时不能直接查询,正确的姿势是把公共祖先anc先求出,然后把这组查询存起来,当访问完anc以后再处理这组查询。那么加上顺序有多大区别呢?其实差不多,只需要多维护一个值罢了:从当前根节点到当前节点的最大利润。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<set>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=50000+10;struct Edge{ int v,next; Edge (){}; Edge(int vv,int nx) {v=vv;next=nx;}}edges[maxn<<1];struct Node{ int u,v,id; Node(){}; Node(int uu,int vv,int ii){u=uu;v=vv;id=ii;}};int head[maxn],val[maxn],ans[maxn],nEdge;int pa[maxn],maxv[maxn],minv[maxn],bestv[maxn],ups[maxn];bool vis[maxn];vector<pair<int,int> >querys[maxn];vector<Node>noq[maxn];int Find(int x){ if(x==pa[x]) return x; Find(pa[x]); int y=pa[x]; ups[x]=max(ups[x],max(ups[y],maxv[x]-minv[y])); bestv[x]=max(bestv[x],max(bestv[y],maxv[y]-minv[x])); maxv[x]=max(maxv[y],maxv[x]); minv[x]=min(minv[y],minv[x]); pa[x]=pa[y]; return pa[x];}void AddEdges(int u,int v){ edges[++nEdge]=Edge(v,head[u]); head[u]=nEdge; edges[++nEdge]=Edge(u,head[v]); head[v]=nEdge;}inline int getbest(int x,int y){ int res=max(bestv[x],ups[y]); res=max(maxv[y]-minv[x],res); return res;}void tarjan(int u,int fa){ pa[u]=u;bestv[u]=ups[u]=0; maxv[u]=minv[u]=val[u]; vis[u]=true; int v,size,anc; pair<int,int>pp; size=querys[u].size(); bool flag; for(int i=0;i<size;++i) { flag=false; pp=querys[u][i]; v=pp.first; if(v<0) {v=-v;flag=true;} if(vis[v]) { anc=Find(v); if(flag) noq[anc].push_back(Node(u,v,pp.second)); else noq[anc].push_back(Node(v,u,pp.second)); } } for(int k=head[u];k!=-1;k=edges[k].next) { v=edges[k].v; if(v==fa) continue; tarjan(v,u); pa[v]=u; } size=noq[u].size(); Node node; for(int i=0;i<size;++i) { node=noq[u][i]; Find(node.u);Find(node.v); ans[node.id]=getbest(node.u,node.v); }}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,q,u,v; memset(head,0xff,sizeof(head)); memset(vis,0,sizeof(vis)); nEdge=-1; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&val[i]); querys[i].clear(); noq[i].clear(); } for(int i=1;i<n;++i) { scanf("%d%d",&u,&v); AddEdges(u,v); } scanf("%d",&q); for(int i=0;i<q;++i) { scanf("%d%d",&u,&v); querys[u].push_back(make_pair(-v,i)); querys[v].push_back(make_pair(u,i)); } tarjan(1,-1); for(int i=0;i<q;++i) printf("%d\n",ans[i]); return 0;}
0 0
- poj 3728 The merchant(tarjan求lca)
- POJ 3728 The merchant (Tarjan LCA)
- *POJ 3728 - The merchant(LCA‘ Tarjan)
- Poj 3728The merchant (tarjan-LCA高级应用)
- The merchant - POJ 3728 LCA
- POJ 3728:The merchant LCA
- |poj 3728|LCA|The merchant
- POJ 3728 The merchant 离线tarjan
- POJ 3728 The merchant LCA+倍增dp
- POJ - 3728 The merchant(dp+LCA)
- POJ 3728The merchant (LCA)
- POJ 3728 The merchant(LCA+DP)
- poj 3728 The merchant(离线LCA 的应用,5级)
- POJ 3728The merchant(dp+LCA+倍增)
- POJ 3728 The merchant(在线倍增LCA)
- POJ 3728 The merchant
- poj 3728 The merchant
- POJ 3728 The merchant
- 教程3:jsp和servlet配合的简单登录页面login.jsp
- 黑马程序员_Java基础_面向对象(二)_06
- -----周立发----------我曾经用过的源代码-mmap把文件映射到内存
- 黑马程序员-高新技术-注解
- hdu 1081To The Max(二维最大连续子串和)
- poj 3728 The merchant(tarjan求lca)
- No tab content FrameLayout found for id xxxxxxx
- PHP开发环境配置——Wamp+NetBeans
- SRM 561
- 精简双向链表的插入代码
- QTCreator + MSVC10编译器 使用boost::filesystem 时 error LNK2019: codecvt ... 问题的解决
- c语言gmail基于openssl的简易程序
- windows8 文件属性没有“安全”选项卡
- poj3071 Football