寒假集训 Day 9 K题 HDU 6201 transaction

HDU-6201transaction “朋友”交易


题目大意:

有 n 个城市 , 城市之间有具有长度的路相连( 长度即路上的花费 ) , 在每个城市都有某种货品的买入和卖出且价格不同 , 可以在一个城市买入一个货物 , 然后再另一个城市卖出 , 问最大的收益是多少 。


解题思路:

  • 用 STL 的 vector 建图 ,并储存路上花费。
  • 用两个数组来分别存储在某个城市 i 的当前最少花费 dp[i][0] 和 当前最大收益 dp[i][1]。
  • 设一个初始根节点 -1,从节点 -1 -> 节点 1 开始利用 dfs 遍历这张图 , 同时更新相应的 dp 数组的值。

这种类型的将图转化为树并利用动态规划来解决问题的思路,称为树状DP


AC代码:

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define rep(i,l,p) for(int i=l; i<=p; i++)
#define drep(i,p,l) for(int i=p; i>=l; i--)
#define rush() int T; scanf("%d",&T); while(T--)
using namespace std;

const int maxN = 1e5+5;
int n,ans;
int dp[maxN][2];
int val[maxN];
struct node{
    int v,w;
    node(int _v,int _w):v(_v),w(_w){}
};
vector<node> vec[maxN];
void dfs(int pre,int u){
//  if ( pre == u) return ;
//  used[u] = true;
    dp[u][0] = -val[u];
    dp[u][1] = val[u];
    for(int i = 0;i< vec[u].size();i++){
        int v = vec[u][i].v;
        int w = vec[u][i].w;
        if ( v ==pre) continue;
        dfs(u,v);

        dp[u][0] = max(dp[v][0] - w, dp[u][0]);
        dp[u][1] = max(dp[u][1] , dp[v][1] -w);
    }
    ans = max(ans,dp[u][0]+ dp[u][1]);
    return ;
}
void ini(){
    memset(dp,0,sizeof(dp));
    rep(i,0,n) vec[i].clear();
    ans = 0;
    return ;
}
int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    rush(){
        ini();
        int u,v,w;
        scanf("%d",&n);
        rep(i,1,n) scanf("%d",&val[i]);
        rep(i,1,n-1){
            scanf("%d%d%d",&u,&v,&w);
            vec[u].push_back(node(v,w));
            vec[v].push_back(node(u,w));//
        }
        //cout << "    pppp" << endl;
        dfs(-1,1);
        cout << ans << endl;
    }
    return 0;

}

猜你喜欢

转载自blog.csdn.net/Hagtaril/article/details/79230162