题链:http://poj.org/problem?id=3728
题述:一个树有N个节点,每个节点都有同一件物品,但不同的节点价格不相同,给出每个节点的价钱,Q次询问x,y对于每次询问求从x到y进行一次买卖最大可以获取的利润。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <cstdlib> using namespace std; const int inf=20000000, N=50010; struct edge { int v,id,nx; }e[3][N*2]; int i,n,m,size,u,v,head[3][N]; int uu[N],vv[N],w[N],ans[N],up[N],down[N],maxw[N],minw[N],f[N]; bool b[N]; void add(int u,int v,int id,int p) { size++; e[p][size].v=v; e[p][size].id=id; e[p][size].nx=head[p][u]; head[p][u]=size; } void init() { size=0; for(i=0;i<=n;i++) { head[0][i]=head[1][i]=head[2][i]=-1; b[i]=false; } for(i=1;i<=n;i++) { scanf("%d",&w[i]); up[i]=down[i]=0; maxw[i]=minw[i]=w[i]; } for(i=1;i<n;i++) { scanf("%d%d",&u,&v); add(u,v,i,0); add(v,u,i,0); } size=0; scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d%d",&uu[i],&vv[i]); add(uu[i],vv[i],i,1); add(vv[i],uu[i],i,1); } } int Max(int a,int b) { return (a>b)?a:b; } int Min(int a,int b) { return (a<b)?a:b; } int find(int v) { if (v==f[v]) return f[v]; int fa=f[v]; f[v]=find(f[v]); up[v]=Max(Max(up[v],up[fa]),maxw[fa]-minw[v]); down[v]=Max(Max(down[v],down[fa]),maxw[v]-minw[fa]); maxw[v]=Max(maxw[v],maxw[fa]); minw[v]=Min(minw[v],minw[fa]); return f[v]; } void lca(int u) { int i,v,id,fa; b[u]=true; f[u]=u; i=head[1][u]; while (i!=-1) { v=e[1][i].v; id=e[1][i].id; if (b[v]) { fa=find(v); add(fa,v,id,2); } i=e[1][i].nx; } i=head[0][u]; while (i!=-1) { v=e[0][i].v; if (!b[v]) { lca(v); f[v]=u; } i=e[0][i].nx; } i=head[2][u]; while (i!=-1) { id=e[2][i].id; find(uu[id]); find(vv[id]); ans[id]=Max(Max(up[uu[id]],down[vv[id]]),maxw[vv[id]]-minw[uu[id]]); i=e[2][i].nx; } } int main() { while (scanf("%d",&n)==1) { init(); size=0; lca(1); for(i=1;i<=m;i++) printf("%d\n",ans[i]); } return 0; }
时间: 2024-11-10 01:15:49