Wunder Fund Round 2016 D. Hamiltonian Spanning Tree

分析:樹形DP
主要看x

dp[u][1]=min{dp[v0][1]dp[v0][0]}+{dp[v][0]}

dp[u][0] :如果u 的子節點中有dp[v1][1]+dp[v2][1]<=dp[v1][0]+dp[v1][0] 的,那麼dp[u][0]=dp[u][1]1 ,不然dp[u][0]=dp[u][1]

代碼:

#include <bits/stdc++.h>

using namespace std;

#define FOR(i,x,y)  for(int i = x;i < y;++ i) 
#define IFOR(i,x,y) for(int i = x;i > y;-- i) 
#define pb  push_back

typedef long long LL;
typedef vector <int>    VI;

const int maxn = 200010;
const int inf = 1<<30;

int dp[maxn][2],du[maxn],n;
LL x,y;

VI mat[maxn];

void dfs(int u,int fa){
    int minx = inf;
    int num = 0,sum = 0;
    FOR(i,0,(int)mat[u].size()){
        int v = mat[u][i];
        if(v == fa) continue;
        dfs(v,u);
        if(dp[v][0] == dp[v][1])    num ++;
        sum += dp[v][0];
        minx = min(dp[v][1]-dp[v][0],minx);
    }
    if(minx == inf) dp[u][1] = 1;
    else    dp[u][1] = minx + sum;
    if(num >= 2)    dp[u][0] = dp[u][1]-1;
    else    dp[u][0] = dp[u][1];
    //printf("id:%d\t dp[u][0]:%d\t dp[u][1]:%d\n",u,dp[u][0],dp[u][1]);
}

int main(){
    scanf("%d%I64d%I64d",&n,&x,&y);
    FOR(i,0,n+1)    mat[i].clear(),du[i] = 0;;
    FOR(i,1,n){
        int u,v;    scanf("%d%d",&u,&v);
        mat[u].pb(v);   mat[v].pb(u);
        du[u] ++;   du[v] ++;
    }
    if(x >= y){
        bool flag = false;
        FOR(i,1,n+1) if(du[i] == n-1) {
            flag = true;break;
        }
        if(flag){
            printf("%I64d\n",y*(n-2)+x);
        }
        else{
            printf("%I64d\n",y*(n-1));
        }
    }
    else{
        dfs(1,-1);
        printf("%I64d\n",(dp[1][0]-1)*y+(n-dp[1][0])*x);
    }
    return 0;
}

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