POJ 3728 The merchant 离线tarjan
2017-10-10 14:16
302 查看
题目链接
http://poj.org/problem?id=3728题意
一件商品在每个城市的价格都不一样,某个商人决定利用这个来赚钱,他想知道从某个起点到某终点,可以获得的最大利润。总共q次询问。思路
对于询问中的u和v,lca为u和v的最近公共祖先up[u] 表示从u往lca方向走能获得的最大利润
down[u]表示从lca方向往u走能获得的最大利润
Max[u] 表示从u到lca这段路径中的最大值
Min[u] 表示从u到lca这段路径中的最小值
这些值的更新是在找祖先的过程中更新
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<string> #include<queue> #include<stack> #include<set> #include<map> #define ll long long using namespace std; const int INF = ( 2e9 ) + 2; const ll maxn = 5e4+10; struct edge { int u,v,next; }e[2*maxn],que[2*maxn],l[2*maxn]; int head1[maxn],head2[maxn],head3[maxn]; int tot1,tot2,tot3; int ans[maxn]; int Max[maxn],Min[maxn],up[maxn],down[maxn],f[maxn]; bool vis[maxn]; void init() { memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); memset(head3,-1,sizeof(head3)); tot1=tot2=tot3=0; } void add_edge(int u,int v) { e[tot1].v=v; e[tot1].next=head1[u]; head1[u]=tot1++; } void add_que(int u,int v) { que[tot2].u=u; que[tot2].v=v; que[tot2].next=head2[u]; head2[u]=tot2++; } void add_lca(int u,int v) { l[tot3].v=v; l[tot3].next=head3[u]; head3[u]=tot3++; } int Find(int x) { if(f[x]==x)return x; int p=f[x]; f[x]=Find(f[x]); up[x]=max(up[x],max(up[p],Max[p]-Min[x])); down[x]=max(down[x],max(down[p],Max[x]-Min[p])); Max[x]=max(Max[x],Max[p]); Min[x]=min(Min[x],Min[p]); return f[x]; } int input(int n) { int u,v,q; for(int i=1;i<=n;i++) { scanf("%d",&Max[i]); Min[i]=Max[i]; up[i]=down[i]=0; } init(); for(int i=1;i<=n-1;i++) { scanf("%d%d",&u,&v); add_edge(u,v); add_edge(v,u); } scanf("%d",&q); for(int i=1;i<=q;i++) { scanf("%d%d",&u,&v); add_que(u,v); add_que(v,u); } return q; } void tarjan(int u) { f[u]=u; vis[u]=true; int v; for(int i=head2[u];i!=-1;i=que[i].next) { v=que[i].v; if(vis[v]) { int LCA=Find(v); add_lca(LCA,i); } } for(int i=head1[u];i!=-1;i=e[i].next) { v=e[i].v; if(!vis[v]) { tarjan(v); f[v]=u; } } for(int i=head3[u];i!=-1;i=l[i].next) { int id=l[i].v; if((id&1))id=id^1; int u=que[id].u,v=que[id].v; Find(u); Find(v); int t=id/2; // 答案要不是在u->lca 这一段中 要不就在lca->v 中,要不就跨越了lca ans[t]=max(up[u],down[v]); ans[t]=max(ans[t],Max[v]-Min[u]); } } void solve(int q) { memset(vis,0,sizeof(vis)); tarjan(1); for(int i=0;i<q;i++) printf("%d\n",ans[i]); } int main() { int n; // freopen("in.txt","r",stdin); while(~scanf("%d",&n)) { int q=input(n); solve(q); } }
相关文章推荐
- POJ - 3728 The merchant【离线LCA[倍增法]】
- poj 3728 The merchant(离线LCA 的应用,5级)
- *POJ 3728 - The merchant(LCA‘ Tarjan)
- poj 3728 The merchant(离线LCA 的应用,5级)
- POJ 3728 The merchant (Tarjan LCA)
- Poj 3728 The merchant (tarjan-LCA高级应用)
- poj 3728 The merchant(tarjan求lca)
- poj 3728 The merchant(LCA)
- POJ 3728 The merchant
- POJ 3728 The merchant 已翻译
- POJ 3728 The merchant - LCA
- POJ 3728 The merchant (LCA)
- |poj 3728|LCA|The merchant
- POJ 1986 Distance Queries(离线tarjan-LCA)
- POJ 3728 The merchant(经典LCA)
- POJ 3728 The merchant(LCA+DP)
- POJ1330(LCA-离线tarjan)
- poj 1470 Closest Common Ancestors 【Tarjan 离线 LCA】
- POJ 1330 ---(线段树在线LCA 与 tarjan离线LCAs)
- poj 1470 关于lca离线tarjan方法的使用