2017 ACM/ICPC Asia Regional Shenyang Online transaction transaction transaction

题目大意:

多组样例,每组输入一棵树,然后书上每个节点有权值,每两个点之间的边有权值,任选两个点,然后让你求这两个点的差值再减去这两点之间的变得权值的最大值;

基本思路:

树型dp,以1节点为根,dfs其子节点,用dmax[k]表示以k节点为根的子树中所能卖的最大价格,dmin[k]表示买书花费的最少价格,ans=max(dmax[k]-dmin[k])。边的花费加到dmax和dmin里面就行。

反思与总结:

蒟蒻只能先到最朴素的超时解法,这个思路真的很难想我觉得;

代码如下:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>

using namespace std;

const int maxn = 100000+10;
typedef long long ll;

struct Node
{
    int v,w,next;
}node[maxn*2];
int head[maxn];
bool vis[maxn];
int dmax[maxn],dmin[maxn],ans[maxn];
int res;
int cnt;
void addEdge(int u,int v,int w)
{
    node[cnt].v=v;
    node[cnt].w=w;
    node[cnt].next=head[u];
    head[u]=cnt++;
}

void dfs(int idx)
{
    vis[idx]=1;
    dmax[idx]=dmin[idx]=ans[idx];
    int v,w;
    for(int i=head[idx];i!=-1;i=node[i].next)
    {
        v=node[i].v;
        w=node[i].w;
        if(vis[v]) continue;
        dfs(v);
        dmax[idx]=max(dmax[idx],dmax[v]-w);
        dmin[idx]=min(dmin[idx],dmin[v]+w);
        res=max(res,dmax[idx]-dmin[idx]);
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        res=-0x3f3f3f3f;
        cnt=0;
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++) scanf("%d",&ans[i]);
        for(int i=1;i<=n-1;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addEdge(u,v,w);
            addEdge(v,u,w);
        }
        dfs(1);
        printf("%d\n",res);
    }
}

  

posted @ 2017-09-11 16:56  愿~得偿所愿,不负时光  阅读(176)  评论(0编辑  收藏  举报