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;
}