2017 Multi-University Training Contest 10 1008 Monkeys HDU 6178 (贪心 读入挂fread)

来源:互联网 发布:王大治知乎 编辑:程序博客网 时间:2024/06/05 03:10

题意:给你一棵n节点的树,现在让你放k个猴子,可以删边,问最少可以剩余几条边,放k个猴子,满足任意一个猴

至少与一只猴子相连。2<=k<=n<=1e5


思路:我们可以知道一条边连两个节点(猴子),用成对的点这样是最节约边使猴子放的尽量多(一条边能放俩猴子)。现在问题就转成就是要找可以有几个对点,可以从树根开始dfs,看他有几个儿子和儿子中已经成对的个

数,若两者之差>=1,则至少存在一个儿子能与它成对,cnt++。

虽然算法是On的,但是读入数据很多,所以需要用到fread读入挂。。


代码:

#include<iostream>#include<cstdio>#include<queue>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const int maxn = 2e5+5;int n, m, k, can, head[maxn], use[maxn];struct node{    int v, next;}edge[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');    }    #undef BUF_SIZE};using namespace fastIO;void addEdge(int u, int v){    edge[k].v = v;    edge[k].next = head[u];    head[u] = k++;}void dfs(int u, int fa){    int cnt = 0, uu = 0;    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].v;        if(v == fa) continue;        dfs(v, u);        cnt++;        uu += use[v];    }    if(cnt-uu >= 1) can++, use[u] = 1;}int main(void){//    freopen("in.txt", "r", stdin);    int t;    read(t);    while(t--)    {        k = can = 0;        memset(head, -1, sizeof(head));        memset(use, 0, sizeof(use));        read(n);        read(m);        for(int i = 2; i <= n; i++)        {            int tmp;            read(tmp);            addEdge(i, tmp);            addEdge(tmp, i);        }        dfs(1, 0);        if(can*2 >= m)            printf("%d\n", (m+1)/2);        else            printf("%d\n", can+(m-can*2));    }    return 0;}/*115 21 1 1 15 31 1 1 15 41 1 1 15 51 1 1 15 21 1 2 25 31 1 2 25 41 1 2 25 51 1 2 24 21 1 24 31 1 24 41 1 2*/


阅读全文
1 0
原创粉丝点击