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