宝藏

来源:互联网 发布:平板 win10 知乎 2017 编辑:程序博客网 时间:2024/04/28 11:46

宝藏
【问题描述】
一棵 个点的树,到达一个点会获得这个点上的宝藏,每个宝藏都有一定的
价值。经过每条边需要支付一定的过路费。每个点只有一个宝藏,但过路费每次
都要交。求从每个点出发能得到的最大收益。
【输入文件】
输入文件为treasure.in。
第一行为一个正整数n。
接下来n-1行,每行三个整数x,y,z ,描述一条边的两个端点 x,y和过路费 。
最后一行n个数,表示每个点上宝藏的价值 ai。
【输出文件】
输出文件为treasure.out。
输出 行,每行一个数。第 行表示从 出发的最大收益。
【输入输出样例】
treasure.in
6
1 2 1
2 3 3
3 4 36
3 6 13
3 5 2
6 8 9 10 13 1
treasure.out
30
29
28
10
30
16
【数据规模和约定】
对于20%的数据,满足n<=10。
对于50%的数据,满足n<=1000。
对于100%的数据,满足1<=n<=300000,1<=z,a[i]<=100000。



dfs1

tree[u]uu

Max[u]u

D[u]Max[u]

Max1[u]

dfs2

tree[u]uu

Max[u]u

Max1[u],D[u]

#include<iostream>#include<cstdio>using namespace std;#define ll long longint num;#define M 600005#define W 300005int vet[M],val[M],Next[M],hed[W],D[W],a[W];ll Max[W],Max1[W],tree[W];inline int read(){    int X=0,w=1; char ch=0;    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();    return X*w;}void calc(int u,int MM,int v){  if (MM>Max[u]){    Max1[u]=Max[u];    Max[u]=MM;    D[u]=v;      return;    }    if (MM>Max1[u]){      Max1[u]=MM;      return;    }}void add(int u,int v,int x){  ++num;  vet[num]=v;  val[num]=x;  Next[num]=hed[u];  hed[u]=num;}void dfs1(int u,int fa){  tree[u]=a[u];    for (int i=hed[u];i!=-1;i=Next[i]){    int v=vet[i];    if (v==fa) continue;    dfs1(v,u);    tree[u]+=max(0ll,tree[v]-val[i]-val[i]);    calc(u,Max[v]-val[i]+tree[v]-max(0ll,tree[v]-val[i]-val[i]),v);  }}void dfs2(int u,int fa){  for (int i=hed[u];i!=-1;i=Next[i]){    int v=vet[i];    if (v==fa) continue;    ll item=tree[u]-val[i]-val[i]-max(0ll,tree[v]-val[i]-val[i]);    tree[v]+=max(0ll,item);    item=min(item,0ll);    if (D[u]==v) calc(v,item+Max1[u]+val[i],u);    else calc(v,item+Max[u]+val[i],u);        dfs2(v,u);  }}int main(){  int n;  n=read();  num=0;    for (int i=1;i<=n;++i) hed[i]=-1;  for (int i=1;i<n;++i){    int x,y,z;    x=read();y=read();z=read();    add(x,y,z);    add(y,x,z);    }    for (int i=1;i<=n;++i) a[i]=read();    dfs1(1,0);    dfs2(1,0);    for (int i=1;i<=n;++i)        printf("%lld\n",tree[i]+Max[i]);  return 0;}
原创粉丝点击