博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 6178 Monkeys
阅读量:5142 次
发布时间:2019-06-13

本文共 2926 字,大约阅读时间需要 9 分钟。

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 153428/153428 K (Java/Others)

Total Submission(s): 1328    Accepted Submission(s): 435

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
 

 

Source
 

 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:       
 
思路:贪心+二分图最大匹配(树形DP)

这题O(n)做竟然卡读入优化。。。。。。。。。。。。。。。。。。。。。。用一般的读入优化竟然TLE。

从大佬哪里求得黑科技,样例输不进去竟然AC了:

namespace IO  {      const int U=40*1024*1024;      char buf[U];    int ptr,sz;    void begin()    {        ptr=0;        sz=fread(buf,1,U,stdin);    }    template
inline bool scan_d (T&t) { while(ptr
<'0'||buf[ptr]>'9')) ptr++; if(ptr>=sz) return false; bool sgn=false; if(buf[ptr]=='-') sgn=true,ptr++; for(t=0;ptr
<=buf[ptr]&&buf[ptr]<='9';ptr++) t=t*10+buf[ptr]-'0'; if(sgn) t=-t; return true; } } using namespace IO;
View Code

①很显然,如果我们最终的答案是一个包含K个点的整个联通块的话,显然答案就是K-1.如果我们是两个共包含K个点的联通块的话,显然答案会对应减少。

所以我们希望分部的情况是尽可能多的联通块,那么理应我们希望将结果分成若干个两两相连的小联通块。

②我们希望构成尽可能多的这样两两相连的小联通块(只用一条边去连接)的话,很显然是需要跑最大二分匹配数。我们知道最小点覆盖==最大二分匹配数,而直接建图跑二分图匈牙利匹配的话,时间复杂度很爆炸,我们知道树形dp可以O(n)求树上的最小点覆盖问题,所以我们直接跑树形Dp即可。

③如果我们最小点覆盖数为ans个,那么分情况讨论即可:

如果k<=ans*2,那么结果就是k/2

如果k>ans*2,那么结果就是k-ans*2+ans(多出来的点直接往上加即可)

如果k是奇数,那么答案再加1.

 

#include
#include
#include
#include
#include
#define MAXN 100010using namespace std;int T,n,k,tot;int dp[MAXN][2];vector
vec[MAXN];namespace IO { const int U=40*1024*1024; char buf[U]; int ptr,sz; void begin() { ptr=0; sz=fread(buf,1,U,stdin); } template
inline bool scan_d (T&t) { while(ptr
<'0'||buf[ptr]>'9')) ptr++; if(ptr>=sz) return false; bool sgn=false; if(buf[ptr]=='-') sgn=true,ptr++; for(t=0;ptr
<=buf[ptr]&&buf[ptr]<='9';ptr++) t=t*10+buf[ptr]-'0'; if(sgn) t=-t; return true; } } using namespace IO;void dfs(int fa,int now){ dp[now][0]=0; dp[now][1]=1; for(int i=0;i
=k) printf("%d\n",(k+1)/2); if(ans*2

 

转载于:https://www.cnblogs.com/cangT-Tlan/p/7580113.html

你可能感兴趣的文章
GridView 动态列上方添加相应的Combox等控件
查看>>
申请开发者账号
查看>>
oracle启动
查看>>
c++模板学习
查看>>
【转】MySQL Event
查看>>
[转]html5监听任何App自带返回键javascript事件
查看>>
mongodb数据备份与还原
查看>>
通俗理解LDA主题模型
查看>>
回射服务器-多路复用 select 01 (阻塞)
查看>>
分享吉林大学机械科学与工程学院,zhao jun 博士的Halcon学习过程及知识分享
查看>>
BitmapData.noise示例
查看>>
肤色阈值分割
查看>>
Android中的菜单
查看>>
【最短路】Vijos P1046 观光旅游
查看>>
Android学习总结——开篇
查看>>
iOS 基础知识
查看>>
PHP 重新格式化var_dump/print_r打印的数组
查看>>
C++11:POD数据类型
查看>>
Delphi中Json格式读写
查看>>
请不要忘记带着梦想时常沐浴阳光
查看>>