zoukankan      html  css  js  c++  java
  • HDU6178 Monkeys

    题意:一棵树有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 == '
    ' || ch == '
    ' || ch == '	';
        }
        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
    ", (k+1)/2);
            else printf("%d
    ", (k-ans));
        }
        return 0;
    }
    /*
    4 4
    1 2 3
    */
  • 相关阅读:
    Android数据的四种存储方式SharedPreferences、SQLite、Content Provider和File
    android的五大布局(layout)
    json数据进行格式化
    将utf-8的中文或者字符都看成一个字符
    Mysql 中 trim 的用法
    生成密码函数
    Eclipse智能提示设置
    Java Jersey2使用总结
    Java对存储过程的调用方法
    Jersey框架
  • 原文地址:https://www.cnblogs.com/Noevon/p/7429787.html
Copyright © 2011-2022 走看看