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

HDU6178 Monkeys

时间:2017-08-26 04:55:27      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:hdu   back   bre   tin   dir   define   保留   monk   ++   

题意:一棵树有n个点,要求在其中的k个点上面放猴子,每一个猴子要与其他猴子中的一只相连,问要保留几条边

题解:分析可得,每一只猴子要和其他猴子相连,有两种情况,第一种是直接配对相连,第二种是单个连到已经配对好的,可以先算出最大匹配数,就相当于最小点覆盖,树上的最小点覆盖可以用树形dp算出,设dp[i][0]代表i这个点不选最小点数,dp[i][1]代表i这个点要选最小点数,那么从根节点开始每一个数dp[i][1] = min(dp[j][0], dp[j][1]);dp[i][0] = dp[j][1];可以算出最大匹配

#include <bits/stdc++.h>
#define ll long long
#define maxn 100100
using namespace std;

int dp[maxn][2], dir[maxn];
vector<int >G[maxn];
namespace fastIO {
    #define BUF_SIZE 1000000
    //fread -> read
    bool IOerror = 0;
    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if(p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if(pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch) {
        return ch ==   || ch == \n || ch == \r || ch == \t;
    }
    inline void read(int &x) {
        char ch;
        while(blank(ch = nc()));
        if(IOerror)
            return;
        for(x = ch - 0; (ch = nc()) >= 0 && ch <= 9; x = x * 10 + ch - 0);
    }
};
using namespace fastIO;
inline void dfs(int x){
    dp[x][0] = 0;
    dp[x][1] = 1;
    dir[x] = 1;
    for(int i=0;i<G[x].size();i++){
        int u = G[x][i];
        if(dir[u] == 1) continue;
        dfs(u);
        dp[x][1] += min(dp[u][0], dp[u][1]);
        dp[x][0] += dp[u][1];
    }
}
int main(){
    int T, k, n, t, root, ans;
    read(T);
    while(T--){
        read(n);read(k);
        for(int i=1;i<=n;i++) G[i].clear();
        memset(dir, 0, sizeof(dir));
        for(int i=1;i<n;i++){
            read(t);
            G[i+1].push_back(t);
            G[t].push_back(i+1);
        }
        for(int i=1;i<=n;i++)
        if(G[i].size() == 1){
            root = i;
            break;
        }
        dfs(root);
        ans = min(dp[root][0], dp[root][1]);
        if(ans*2 > k) printf("%d\n", (k+1)/2);
        else printf("%d\n", (k-ans));
    }
    return 0;
}
/*
4 4
1 2 3
*/

 

HDU6178 Monkeys

标签:hdu   back   bre   tin   dir   define   保留   monk   ++   

原文地址:http://www.cnblogs.com/Noevon/p/7429787.html

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