寒假集訓 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;

}
發佈了37 篇原創文章 · 獲贊 5 · 訪問量 3664
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章