Wunder Fund Round 2016 D. Hamiltonian Spanning Tree

来源:互联网 发布:网络热敏打印机 编辑:程序博客网 时间:2024/04/20 21:26

分析:树形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_backtypedef 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;}
0 0
原创粉丝点击