算法訓練 結點選擇

結點選擇ios

/*
    首先這道題輸入的邊的兩端的結點不是上一行的結點的權值,而是
結點的序號,其次,這道題並無說這個樹是二叉樹而且也沒有說邊左
邊的結點就是父親結點,右邊的結點就是孩子結點,因此這道題樹的存
儲用無向圖來存儲。
    關於算法就是樹形規劃:從葉子結點往上到根節點進行動態規劃,
利用dfs來實現這個葉子節點到根節點。 
    動態規劃的狀態呢分爲:對根節點爲序號爲a的子樹來講呢,
dp[a][0]就是不選當前結點所能選出的結點最大值。
dp[a][1]是選當前結點的能選出的最大值。
關於這個dp的初始化,將全部結點視爲葉子結點,根據狀態呢,顯然dp[a][0]=0,dp[a][1]=這個a點的權值。 
    動態轉移方程見下面程序代碼dfs處。 
*/
#include<iostream>
#include<vector>
using namespace std;
vector<vector<int> > v;
int dp[100005][2]={0};
void dfs(int a, int pre){
    for(int i=0; i<v[a].size(); i++){
        int t=v[a][i];
        if(t!=pre){
            dfs(t, a);
            dp[a][0]+=max(dp[t][0], dp[t][1]);
            dp[a][1]+=dp[t][0];
        }
    }
}
int main(){
    int n, a, b;
    cin>>n;
    v.resize(n+1);
    for(int i=1; i<=n; i++)
        scanf("%d", &dp[i][1]);
    for(int i=0; i<n-1; i++){
        scanf("%d%d", &a, &b);
        v[a].push_back(b);
        v[b].push_back(a);
    }
    dfs(1, 0);
    cout<<max(dp[1][0], dp[1][1])<<endl;
    return 0;
}
相關文章
相關標籤/搜索