Monkeys
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 153428/153428 K (Java/Others)Total Submission(s): 1307 Accepted Submission(s): 431
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.
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).
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
题意:
让你尽可能留下少的边,使得每只猴子都不孤立(即每只猴子至少与与一只猴子相连),输出边数
解析:
尽可能让两只猴子独立地连在一起,这样可以使边最少,当有奇数个猴子时,就使一堆是3个猴子连在一起
这样用dfs深搜,找树中最多有多少个两个连在一起(即匹配)的堆,奇数时还要找一个3个匹配的堆
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
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;
const int MAXN = 2e5;
typedef struct node
{
int u;
int v;
int next;
}node;
node edge[MAXN];
int head[MAXN],cnt;
int flag;
int n,k,num3,num2;
void addedge(int u,int v)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int dfs(int x) //dfs返回在待匹配(前提是能跟上一层匹配)的结点的数量
{
if(head[x]==-1)
{
return 1;
}
int num=0;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
num+=dfs(v);
}
if(flag&&num>=2) //奇数,找一个有3个节点的堆
{
num3=1;
flag=0;
return 0;
}
if(num==0)
{
return 1;
}
else
{
num2++;
return 0;
}
}
int main()
{
int t;
//scanf("%d",&t);
read(t);
while(t--)
{
memset(head,-1,sizeof(head));
cnt=0;
//scanf("%d%d",&n,&k);
read(n);read(k);
for(int i=0;i<n-1;i++)
{
int tmp;
read(tmp);
//scanf("%d",&tmp);
addedge(tmp,i+2);
}
if(k&1) flag=1;
else flag=0;
num3=num2=0;
dfs(1);
if(k&1)
{
if(num3==0)
{
if((k-1)>num2*2)
{
printf("%d\n",num2+k-num2*2);
}
else
{
printf("%d\n",(k-1)/2+1);
}
}
else
{
if((k-3)>num2*2)
{
printf("%d\n",num3*2+num2+k-num2*2-num3*3);
}
else
{
printf("%d\n",(k-3)/2+2);
}
}
}
else
{
if(k>num2*2)
{
printf("%d\n",num2+k-num2*2);
}
else
{
printf("%d\n",k/2);
}
}
}
return 0;
}