POJ

来源:互联网 发布:bose qc35淘宝假货 编辑:程序博客网 时间:2024/06/07 02:17

POJ - 3728传送


题意:给定n个城市,每两个城市之间有且仅有一条路。货物在各个城市的价格不同,在一条路径中,

      商人选择其 中一个城市买进货物,然后在之后的一个城市卖出货物,求所能获得的最大利润。
     对于q次询问,每次询问给定两个整数表示两个城市,输出两城市之间路径所对应的最大利润。
      注意最多只能买一次,然后卖一次。

思路:利用LCA倍增法求解过程,同时求出最大利润。

            在LCA倍增法中,设fa[x][i]表示,x点的2^i的祖宗节点。

            同理设up[x][i]为从x走到fa[x][i]过程能获得的最大利益

                设down[x][i]为从fa[x][i]走到x过程的最大利益

                设fma[x][i]为x和fa[x][i]之间的最大价格

                设fmi[x][i]为x和fa[x][i]之间的最小价格

                在倍增法过程就能快速求解出最大利益

                           注意维护过程

#include<cstring>#include<iostream>#include<cstdio>#include<vector>using namespace std;#define fma fmaxxxxconst int INF=0x3f3f3f3f;const int N=50500;int dep[N],fa[N][20],fma[N][20],fmi[N][20],up[N][20],down[N][20],val[N];int n,m;vector<int>g[N];void dfs(int x,int pa,int d){    dep[x]=d;    for(int i=0;i<g[x].size();i++)    {        int y=g[x][i];        if(y==pa)continue;        fa[y][0]=x;        fma[y][0]=max(val[x],val[y]);        fmi[y][0]=min(val[x],val[y]);        up[y][0]=max(0,val[x]-val[y]);        down[y][0]=max(0,val[y]-val[x]);        dfs(y,x,d+1);    }}void init(){    for(int j=1;j<=m;j++)    {        for(int i=1;i<=n;i++)        {            if(fa[i][j-1]<0){fa[i][j-1]=-1;continue;}            fa[i][j]=fa[fa[i][j-1]][j-1];            fma[i][j]=max(fma[i][j-1],fma[fa[i][j-1]][j-1]);            fmi[i][j]=min(fmi[i][j-1],fmi[fa[i][j-1]][j-1]);            up[i][j]=max(up[i][j-1],up[fa[i][j-1]][j-1]);            up[i][j]=max(up[i][j],fma[fa[i][j-1]][j-1]-fmi[i][j-1]);            down[i][j]=max(down[i][j-1],down[fa[i][j-1]][j-1]);            down[i][j]=max(down[i][j],fma[i][j-1]-fmi[fa[i][j-1]][j-1]);        }    }}int LCA(int x,int y){    int ans=0,mixx=val[x],maxx=val[y];    if(dep[x]>dep[y])    {        for(int i=0;i<=m;i++)        {            if((dep[x]-dep[y])&(1<<i))            {                ans=max(ans,up[x][i]);                ans=max(ans,fma[x][i]-mixx);                mixx=min(mixx,fmi[x][i]);                x=fa[x][i];            }        }    }    else    {        for(int i=0;i<=m;i++)        {            if((dep[y]-dep[x])&(1<<i))            {                ans=max(ans,down[y][i]);                ans=max(ans,maxx-fmi[y][i]);                maxx=max(maxx,fma[y][i]);                y=fa[y][i];            }        }    }    if(x==y)    {        ;    }    else    {        for(int i=m;i>=0;i--)        {            if(fa[x][i]!=fa[y][i])            {                ans=max(ans,up[x][i]);                ans=max(ans,fma[x][i]-mixx);                mixx=min(mixx,fmi[x][i]);                ans=max(ans,down[y][i]);                ans=max(ans,maxx-fmi[y][i]);                maxx=max(maxx,fma[y][i]);                x=fa[x][i];                y=fa[y][i];            }        }    mixx=min(mixx,fmi[x][0]);    maxx=max(maxx,fma[y][0]);    }    ans=max(ans,maxx-mixx);    printf("%d\n",ans);    return fa[x][0];}int main(){    int x,y;    while(scanf("%d",&n)!=EOF)    {        m=0;        for(int i=1;i<=n;i++)            g[i].clear();        while(n>=(1<<m))m++;        for(int i=1;i<=n;i++)            scanf("%d",&val[i]);        for(int i=1;i<n;i++)        {            scanf("%d%d",&x,&y);            g[x].push_back(y);            g[y].push_back(x);        }        fa[1][0]=-1;        dfs(1,-1,1);        init();        int TAT;        scanf("%d",&TAT);        while(TAT--)        {            scanf("%d%d",&x,&y);            int ret=LCA(x,y);            //-cout<<ret<<"    **"<<endl;        }    }    return 0;}


原创粉丝点击