HDU - 6178 Monkeys(DFS+究极输入外挂)
2017-08-24 23:55
260 查看
Monkeys
Problem DescriptionThere 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,…,aN−1,
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
2017 Multi-University Training Contest - Team 10
题意:给你一棵树,要你求最少的边使得所有猴子都有任意一个同伴,有边相连即为同伴。
解题思路:很容易就会想到,两两配对是最优的。因此只要深搜这棵树,将所有可以两两配对的结点两两配对(有些结点可能有相同的祖先,所以不能配对),然后求出最多可以占多少个节点。然后再分情况讨论,详细看代码注释。
另外这题要开究极输入外挂……本地不能调试那种……fread外挂才能过……TLE到怀疑人生……也有可能是我算法不够优吧
#include<iostream>
#include<deque>
#include<memory.h>
#include<stdio.h>
#include<map>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
#define INF (1LL<<62)
#define ll long long int
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;
/*究极输入外挂*/
int v2[200005],nxt[200005];
int head[200005];
int edge_num;
void insert_edge(int v,int u){
v2[edge_num]=u;
nxt[edge_num]=head[v];
head[v]=edge_num++;
}
int N,K,temp;
bool vis[200005];
int ans;
//深搜配对
void dfs(int v,int par){
for(int i=head[v];~i;i=nxt[i]){
//如果不是指向父亲的边
if(v2[i]!=par){
dfs(v2[i],v);//往下搜
//并且都没有配对过
if(!vis[v2[i]]&&!vis[v]){
vis[v]=vis[v2[i]]=true;
ans+=2;//占点数+2
}
}
}
}
int main()
{
int t;
read(t);
while(t--){
read(N);
read(K);
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
edge_num=0;
for(int i=2;i<=N;i++){
read(temp);
insert_edge(i,temp);
insert_edge(temp,i);
}
ans=0;//存最多可以占多少个点
dfs(1,0);
//如果配对数比K小,那么肯定只能占
if(ans<K)
ans=K-ans/2;//实际上是ans/2+K-ans,意思是先把点占满最少要ans/2条边,然后每多一个猴子,就要多占一条边。
else if(K&1)//K要区分奇偶
ans=K/2+1;
else
ans=K/2;
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- 【DFS求树的最大二分匹配+输入外挂】HDU 6178 Monkeys
- HDU 6178 Monkeys【dfs】【输入外挂模板】
- HDU 6178 Monkeys【DFS+输入输出外挂】
- HDU 6178 && 2017 多校训练:Monkeys(DFS)
- HDU 6178 Monkeys(贪心+dfs)
- HDU 6178 Monkeys (贪心+输入挂)
- Hdu 5147 Sequence II(树状数字 or 线段树 + 输入外挂 前缀和+后缀和)
- HDU 6178 Monkeys(树上的二分匹配)
- hdu 5429 Geometric Progression(java 高精度+java输入外挂)
- 2017多校第10场 HDU 6178 Monkeys 贪心,或者DP
- Hdu 6178 Monkeys【树形Dp-最小点覆盖+贪心思维】
- HDU 6178 Monkeys(树上的二分匹配+fread)
- 【51nod 1737 配对】+ 链式前向星 + dfs + 输入外挂
- HDU 6178 Monkeys
- 2017 多校训练第十场 HDU 6178 Monkeys 最小点覆盖+树形DP
- hdu 1181 dfs 注意输入
- hdu 5183-Negative and Positive (NP) (hash+输入外挂)
- 2017 Multi-University Training Contest 10 && HDU 6178 Monkeys 【贪心||树形DP】
- HDU-6178 Monkeys - 2017 Multi-University Training Contest - Team 10(树形DP)
- hdu-6178-Monkeys(fast IO)