【多校训练】hdu 6178 Monkeys 贪心+dfs+读入挂模版

20 篇文章 0 订阅
16 篇文章 0 订阅

Problem Description
There is a tree having N vertices. In the tree there are K monkeys (K <= N). A vertex can be occupied by at most one monkey. They want to remove some edges and leave minimum edges, but each monkey must be connected to at least one other monkey through the remaining edges.
Print the minimum possible number of remaining edges.
 

Input
The first line contains an integer T (1 <= T <= 100), the number of test cases. 
Each test case begins with a line containing two integers N and K (2 <= K <= N <= 100000). The second line contains N-1 space-separated integers  a1,a2,,aN1 , it means that there is an edge between vertex  ai  and vertex i+1 (1 <=  ai  <= i).
 

Output
For each test case, print the minimum possible number of remaining edges.
 

Sample Input
  
  
2 4 4 1 2 3 4 3 1 1 1
 

Sample Output
  
  
2 2

题意:

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

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


思路:

用dfs搜索点对,点对中两个点只需要一条边,其余每个点需要一条边相连。需要读入挂加速。


//
//  main.cpp
//  1008
//
//  Created by zc on 2017/8/25.
//  Copyright © 2017年 zc. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=220000;
const int M=440000;
int d[N],sum;

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;


struct node
{
    int next,v;
}e[M];
int head[N],cnt;

void init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
}

void add(int u,int v)
{
    e[cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

int dfs(int u,int fa)
{
    int flag=0;
    for(int i=head[u];i+1;i=e[i].next)
    {
        int v=e[i].v;
        if(v==fa)   continue;
        if(!dfs(v,u))   flag=1;
    }
    sum+=flag;
    return flag;
}

int main(int argc, const char * argv[]) {
    int T,n,k;
    read(T);
    while(T--)
    {
        init();
        read(n);read(k);
        memset(d,0,sizeof(d));
        for(int i=2;i<=n;i++)
        {
            int t;
            read(t);
            add(t,i);
            add(i,t);
        }
        sum=0;
        dfs(1,-1);
        int ans;
        if(k<=sum*2)   ans=(k+1)/2;
        else    ans=k-sum;
        printf("%d\n",ans);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值