码迷,mamicode.com
首页 > 其他好文 > 详细

[hdu4714 Tree2cycle]树形DP

时间:2015-08-20 01:16:42      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:

题意:给一棵树,删边和加边的代价都为1,求把树变成一个圈所花的最小代价。

思路:对原树进行删边操作,直到将原树分成若干条链,然后通过在链之间添加边形成圈,由于删边和加边一一对应,且最后需要额外一条边连成圈,所以有:

最小代价=(最小链数-1)*2+1=最小链数*2-1。

令dp[i][0]表示i不和i的父亲相连,i这颗子树所形成的最少链数,dp[i][1]表示i和i的父亲相连,i这颗子树所形成的最少链数,则:

dp[i][0]=∑dp[j][0]+dp[p][1]-dp[p][0] + dp[q][1]-dp[q][0]-1

dp[i][1]=∑dp[j][0]+dp[p][1]-dp[p][0]

其中,j是i的子节点,p是满足dp[j][1]-dp[j][0]最小的j,q是满足dp[j][1]-dp[j][0]第二小的j。

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define copy(a, b)          memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

//#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
//#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

const double PI = acos(-1.0);
const int INF = 1e9 + 7;
const double EPS = 1e-12;

/* -------------------------------------------------------------------------------- */

const int maxn = 1e6 + 7;

pii E[maxn * 2];
int SZ;
int Next[maxn * 2];
int last[maxn];
int son[maxn];

void add(int u, int v) {
    E[SZ ++] = mp(u, v);
    E[SZ ++] = mp(v, u);
    Next[SZ - 2] = last[u];
    last[u] = SZ - 2;
    Next[SZ - 1] = last[v];
    last[v] = SZ - 1;
}

int vis[maxn], dp[maxn][2];

void dfs(int rt) {
    vis[rt] = true;
    int ans = 0, minv1 = INF, minv2 = INF, sum = 0, sum1 = 0, cnt = 0;
    for (int i = last[rt]; ~i; i = Next[i]) {
        int v = E[i].Y;
        if (!vis[v]) {
            dfs(v);
            cnt ++;
            sum += dp[v][0];
            sum1 += dp[v][1];
            int buf = dp[v][1] - dp[v][0];
            if (buf < minv1) {
                minv2 = minv1;
                minv1 = buf;
            }
            else {
                if (buf < minv2) minv2 = buf;
            }
        }
    }
    if (cnt == 0) dp[rt][0] = dp[rt][1] = 1;
    else if (cnt == 1) dp[rt][0] = dp[rt][1] = sum1;
    else if (cnt >= 2) {
        dp[rt][0] = sum + minv1 + minv2 - 1;
        dp[rt][1] = sum + minv1;
    }
//    printf("%d: %d %d\n", rt, dp[rt][0], dp[rt][1]);
}


int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int T;
    cin >> T;
    while (T --) {
        int n;
        cin >> n;
        SZ = 0;
        fillchar(last, - 1);
        fillchar(Next, - 1);
        for (int i = 1; i < n; i ++) {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
        }
        fillchar(vis, 0);
        dfs(1);
        cout << dp[1][0] * 2 - 1 << endl;
    }
    return 0;
}

[hdu4714 Tree2cycle]树形DP

标签:

原文地址:http://www.cnblogs.com/jklongint/p/4743917.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!