zoukankan      html  css  js  c++  java
  • [hdu4714 Tree2cycle]树形DP

    题意:给一棵树,删边和加边的代价都为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
    ", 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;
    }
    
  • 相关阅读:
    pip源配置
    Linux:supervisor命令的使用
    uWSGI+Nginx+Flask在Linux下的部署
    MongoDB的使用[转]
    用python获取服务器硬件信息[转]
    python:virtualenv的使用
    Django笔记:常见故障排除
    常用资源网站链接
    Scrapy笔记:持久化,Feed exports的使用
    Scrapy笔记:使用代理ip
  • 原文地址:https://www.cnblogs.com/jklongint/p/4743917.html
Copyright © 2011-2022 走看看