Description

企鹅国的网吧们之间由网线互相连接,形成一棵树的结构。现在由于冬天到了,供暖部门缺少燃料,于是他们决定去拆一些网线来做燃料。但是现在有K只企鹅要上网和别人联机游戏,所以他们需要把这K只企鹅安排到不同的机房(两只企鹅在同一个机房会吵架),然后拆掉一些网线,但是需要保证每只企鹅至少还能通过留下来的网线和至少另一只企鹅联机游戏。
所以他们想知道,最少需要保留多少根网线?
 

Input

第一行一个整数T,表示数据组数;
每组数据第一行两个整数N,K,表示总共的机房数目和企鹅数目。
第二行N-1个整数,第i个整数Ai表示机房i+1和机房Ai有一根网线连接(1≤Ai≤i)。

Output

每组数据输出一个整数表示最少保留的网线数目。
 

Sample Input

2
4 4
1 2 3
4 3
1 1 1

Sample Output

2
2
 

Data Constraint

对于30%的数据:N≤15;
对于50%的数据:N≤300;
对于70%的数据:N≤2000;
对于100%的数据:2≤K≤N≤100000,T≤10。

最优的情况是一条边正好站两个企鹅,这样会使得保留下来的边最少。

我们怎么求呢?

设ans为在这棵树中满足一条边被两个点站的点对的个数*2, 即点数。

那么如果ans >= k,直接输出(k+1)/2.

如果ans < k, 那么企鹅的站位一定有出现菊花图的样子,我们至多可以满足ans个点找到自己的匹配,剩下的(k-ans)个企鹅只能和别的企鹅链接形成菊花图的样子。

这样它自己站一条边, 所以输出ans / 2 + (k - ans)。

接下来的问题是如何找出ans。

考虑树形DP, 设f[i][0/1]为i的子树中,i这个节点选/不选的最大的两个点相互匹配的点数。

那么显然有f[u][0] += f[v][1];

f[u][1] = max(f[u][0] - f[v][1] + f[v][0] + 2),

解释一下:把式子变一下 $\large f[u][1]=(\sum f[v'][1])-f[v][1]+f[v][0]+2$

因为这个点和枚举的v形成了一个匹配, 所以+2.

写起来不是很难。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline int read() {
int res=;char c=getchar();bool f=;
while(!isdigit(c)) {if(c=='-')f=;c=getchar();}
while(isdigit(c))res=(res<<)+(res<<)+(c^),c=getchar();
return f?-res:res;
}
int T, n, k;
struct edge {
int nxt, to;
}ed[];
int head[], cnt;
inline void add(int x, int y) {
ed[++cnt] = (edge){head[x], y};
head[x] = cnt;
}
int f[][]; void dfs(int x, int fa)
{
for (int i = head[x] ; i ; i = ed[i].nxt)
{
int to = ed[i].to;
if (to == fa) continue;
dfs(to, x);
f[x][] += f[to][];
}
for (int i = head[x] ; i ; i = ed[i].nxt)
{
int to = ed[i].to;
if (to == fa) continue;
f[x][] = max(f[x][], f[x][] - f[to][] + f[to][] + );
}
} int main()
{
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
T = read();
while(T--)
{
cnt = ;
memset(head, , sizeof head);
memset(f, , sizeof f);
n = read(), k = read();
for (int i = ; i <= n - ; i ++)
{
int x = read();
add(x, i + ), add(i + , x);
}
dfs(, );
int ans = max(f[][], f[][]);
if (ans >= k) printf("%d\n", (k + ) / );
else printf("%d\n", ans / + (k - ans));
}
return ;
}

[JZOJ5455]【NOIP2017提高A组冲刺11.6】拆网线的更多相关文章

  1. JZOJ 5462. 【NOIP2017提高A组冲刺11.8】好文章

    5462. [NOIP2017提高A组冲刺11.8]好文章 (File IO): input:article.in output:article.out Time Limits: 1000 ms  M ...

  2. 5458. 【NOIP2017提高A组冲刺11.7】质数

    5458. [NOIP2017提高A组冲刺11.7]质数 (File IO): input:prime.in output:prime.out Time Limits: 1000 ms  Memory ...

  3. JZOJ 5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列

    5456. [NOIP2017提高A组冲刺11.6]奇怪的队列 (File IO): input:queue.in output:queue.out Time Limits: 1000 ms  Mem ...

  4. JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室

    5459. [NOIP2017提高A组冲刺11.7]密室 (File IO): input:room.in output:room.out Time Limits: 1000 ms  Memory L ...

  5. JZOJ 5455. 【NOIP2017提高A组冲刺11.6】拆网线

    455. [NOIP2017提高A组冲刺11.6]拆网线 (File IO): input:tree.in output:tree.out Time Limits: 1000 ms  Memory L ...

  6. JZOJ 5461. 【NOIP2017提高A组冲刺11.8】购物

    5461. [NOIP2017提高A组冲刺11.8]购物 (File IO): input:shopping.in output:shopping.out Time Limits: 1000 ms   ...

  7. 【NOIP2017提高A组冲刺11.8】好文章

    #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> us ...

  8. 【NOIP2017提高A组冲刺11.6】拆网线

    和syq大兄弟吐槽题目不小心yy出了正解.. 最优的选法就是选两个两个相互独立的,欸这不就是最大匹配吗?那多的企鹅就新加一条边呗?不够的就除以2上取整呗? 欸?AC了? 树也是一个二分图,最大匹配=最 ...

  9. 【NOIP2017提高A组冲刺11.8】购物

    这个范围对DP不友好,和CF的一道C题非常像,贪心+后悔. 先使用k个优惠券购买k个q最小的(钱不购买则退出),同时把这k个p[i]-q[i]放入小根堆,然后将剩下的n-k个按p升序排序,记小根堆堆顶 ...

随机推荐

  1. FPGA 开发详细流程你了解吗?

    FPGA 的详细开发流程就是利用 EDA 开发工具对 FPGA 芯片进行开发的过程. FPGA 的详细开发流程如下所示,主要包括电路设计.设计输入.综合(优化).布局布线(实现与优化).编程配置五大步 ...

  2. JQuery对于动态生成的标签绑定事件失效

    JQuery对整个html文档进行dom操作后,我们要想动态绑定事件,有两种方法 1.在进行dom操作时,在标签中写上onclick="afun()" 2.利用document的操 ...

  3. 使用python asyncio+aiohttp做接口测试(TODO)

    线程是操作系统层面的“并行”, 协程是应用程序层面的“并行”. 协程本质上就是:提供一个环境,保存一些需要等待的任务,当这些任务可以执行(等待结束)的时候,能够执行.再等待的过程中,程序可以执行别的任 ...

  4. ubuntu13启动屏幕亮度0解决方法

    在终端输入: sudo gedit /etc/default/grub 找到 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDL ...

  5. WEB开发中常见的漏洞

    一.SQL注入漏洞 SQL注入攻击(SQL Injection),简称注入攻击.SQL注入,被广泛用于非法获取网站控制权,是发生在应用程序的数据库层上的安全漏洞.在设计程序,忽略了对输入字符串中夹带的 ...

  6. Python邮件发送功能

    import smtplibfrom email.mime.text import MIMEText_user = "1147016115@qq.com"#发件人_pwd = &q ...

  7. 应用角度看kafka的术语和功能

    kafka的术语(Terminology) Topic 和Consumer Group Topic 每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic.(物理上不同 Topic ...

  8. 在github上部署第二个repository

    想在github上保存一些平时写的测试程序,所以就建立了一个repository:https://github.com/commshare/testProgram 建立好之后,怎么把本地的代码上传呢. ...

  9. element取表格对应id数据

    <el-button size="mini" type="danger" @click="editor(scope.row)"> ...

  10. python 对excel进行截图

    工作中需要对excel的单元格区域进行截图,以前是调用vba进行(走了很多弯路,虽然能实现,但比较low),后来逐步发现python的win32com与vba师出同门,很多方法操作都是类似的. 可以对 ...