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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值