POJ 3728 The merchant 离线tarjan

来源:互联网 发布:古筝软件下载手机 编辑:程序博客网 时间:2024/06/06 03:37

题目链接

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 longusing 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);    }}