Monkeys
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 153428/153428 K (Java/Others)
Total Submission(s): 729 Accepted Submission(s): 234
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,…,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
题目大意:给出一棵树和
k
个猴子,砍掉一些边,每只猴子至少要与另一只猴子直接相连,问最后剩的边数最少为多少?
解题思路:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<fstream>
using namespace std;
const int MAXN=1e5+5;
const int INF=0x3f3f3f3f;
bool vis[MAXN];
int ans,tot,head[MAXN];
namespace fastIO {
#define BUF_SIZE 100000
//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 Edge
{
int to,nxt;
}e[MAXN*2];
void addedge(int u,int v)
{
e[tot].to=v;
e[tot].nxt=head[u];
head[u]=tot++;
}
void dfs(int u,int fa)
{
int son=0,mon=0;
for(int i=head[u];i!=-1;i=e[i].nxt)
{
int to=e[i].to;
if(to==fa) continue;
dfs(to,u);
son++;
if(vis[to]) mon++;
}
if(son>mon) vis[u]=true,ans++;
}
int main()
{
//freopen("in.txt","r",stdin);
int T;
read(T);
//scanf("%d",&T);
int n,k;
while(T--)
{
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
tot=0;
read(n);read(k);
//scanf("%d%d",&n,&k);
int tmp;
for(int i=2;i<=n;i++)
{
read(tmp);
//scanf("%d",&tmp);
addedge(tmp,i);addedge(i,tmp);
}
ans=0;
dfs(1,-1);
if(2*ans>=k)
{
if(k&1) printf("%d\n",(k-1)/2+1);
else printf("%d\n",k/2);
}else
{
printf("%d\n",ans+(k-2*ans));
}
}
return 0;
}

探讨了在一棵树上,通过移除部分边使每只猴子至少与其他一只猴子保持连接的情况下,剩余边数最少的问题。使用深度优先搜索算法找到解决方案。
598

被折叠的 条评论
为什么被折叠?



