hdu 6201 transaction transaction transaction tree dp

来源:互联网 发布:魔灵召唤无法连接网络7 编辑:程序博客网 时间:2024/05/22 03:37

题目链接


题意:


有n个城市,每个城市有一本书,买书需要花钱,卖书可以得到钱,并且两个城市之间的距离也有花费。选择两个城市,一个城市买书一个城市卖书,问得到的最大收益。保证给定的n-1条边组成一棵树


思路:


再次栽在了水题上,想过tree dp 维护一个买的值和卖的值,结果没实现 = =,感觉无法解决跨子树的情况 。其实tree dp 最好的方法就是想明白要记录什么,然后自己手动递归一下到最底层看看是否符合.


这个题目只需要记录一个以每个点为根的子树当中根节点走到某点卖书的最大值和某个点买本书到根节点的最大值(因为最后求的是盈利,即卖书的钱减买书的钱和花费,所以买书的花费存的是负的,这样最大的其实就是花费最小的),然后维护一个最大的就好.

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<set>#include<vector>#include<queue>#include<map>#define inf 0x3f3f3f3f#define pb push_back #define mk make_pair using namespace std;typedef long long ll;const ll mod=1e9+7;const int maxn=1e5+10;int dp[maxn][3],ans;int val[maxn],n;vector<pair<int,int> > vt[maxn]; void dfs(int x,int fa){    dp[x][0] = -val[x];    dp[x][1] = val[x];    for(int i = 0;i < vt[x].size();++i)    {        int v = vt[x][i].first;        int w = vt[x][i].second;        if(v == fa) continue;        dfs(v,x);        dp[x][0] = max(dp[x][0],dp[v][0]-w);        dp[x][1] = max(dp[x][1],dp[v][1]-w);     }    ans = max(ans,dp[x][0]+dp[x][1]);    return ;} int main(){    int _;    cin>>_;    while(_--)    {        scanf("%d",&n);        for(int i = 0;i <= n;i++)        vt[i].clear();        for(int i = 1;i <= n;++i)        {            scanf("%d",&val[i]);        }        for(int i = 1;i < n;++i)        {            int u,v,w;            scanf("%d %d %d",&u,&v,&w);            vt[u].pb(mk(v,w));            vt[v].pb(mk(u,w));        }        ans = 0;        dfs(1,-1);        printf("%d\n",ans);    }    return 0;}


原创粉丝点击