hdu 6178 Monkeys

来源:互联网 发布:如何下载别人淘宝视频 编辑:程序博客网 时间:2024/06/12 04:11

Problem

acm.hdu.edu.cn/showproblem.php?pid=6178

Meaning

要在一棵 n 个点的树上放 k 只猴子,然后删掉尽量多的边,使得删边后,每只猴子都至少和另外一只猴子相连,问最后剩下的边数。

Analysis

因为至少两只猴子相连,就贪心地把树拆成“点 - 边 - 点”这样的片段,成对地放猴子,如果还不够放,剩下的结点都是孤立的,要补边连上任意一对,每补一只猴子就加一条边。可以一次简单地深搜贪心拆树,或者一次简单的树型 DP。

  • 这题的考点主要是读入外挂。模板来自这次多校第一场的最后一题的标程。(看这程序好像是只能读非负整数)
  • 这个读入挂想在本地测试的时候,要用freopen()来输入重定向,直接用stdin键盘输入是行的;但交题的时候不用加重定向(除非题目说明)

Code

#include <cstdio>#include <cstring>using namespace std;/*------- 开挂 -------*/namespace fastIO {    #define BUF_SIZE 100000    // fread -> read    bool IOerror = 0;    char nc() {        static char buf[BUF_SIZE], *pl = buf + BUF_SIZE, *pr = buf + BUF_SIZE;        if(pl == pr) {            pl = buf;            pr = buf + fread(buf, 1, BUF_SIZE, stdin);            if(pr == pl) {                IOerror = 1;                return -1;            }        }        return *pl++;    }    inline bool blank(char ch) {        return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';    }    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');    }    #undef BUF_SIZE};using namespace fastIO;/*------- 完结 -------*/const int N = 100000;int head[N+1], to[N<<1], nxt[N<<1];void add_edge(int f, int t, int sz){    to[sz] = t;    nxt[sz] = head[f];    head[f] = sz;}bool paired[N+1];int odd; // 落单的点数void dfs(int v, int f){    for(int i = head[v]; ~i; i = nxt[i])        if(to[i] != f)        {            dfs(to[i], v);            if(!paired[to[i]]) // 子结点未被配对            {                if(paired[v]) // 当前结点已配对, 不能跟它配                    ++odd; // 子结点落单                else // 当前结点跟它配对                    paired[v] = paired[to[i]] = true;            }        }}int main(){    int T;    read(T);    for(int n, k, ans; T--; )    {        read(n);        read(k);        memset(head, -1, sizeof head);        for(int f = 2, t, sz = 0; f <= n; ++f)        {            read(t);            add_edge(f, t, sz++);            add_edge(t, f, sz++);        }        memset(paired, false, sizeof paired);        odd = 0;        dfs(1, 0);        odd += !paired[1]; // 树根是否落单        int num = (n - odd) / 2; // 成功配对的对数        if(2 * num < k) // 配对点数不足 k            ans = num + k - num * 2;        else if(k & 1) // k 是奇数            ans = k / 2 + 1;        else // k 是偶数            ans = k / 2;        printf("%d\n", ans);    }    return 0;}
原创粉丝点击