一开始想到了二分图匹配,找出最大匹配以后如果还有猴子剩下,答案就是匹配数加剩下的猴子数。
后来写完就觉得匈牙利复杂度不够,瞎交了一发 tle了
后来知道了dfs的暴力匹配,创建一个0点,和1 相连,然后跑dfs,见到一条边,两个点都没有被选的话就选。
dfs以后如果0被选了 匹配数就减1,然后算答案
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 100000+10;
int n,k,a;
vector<int>G[maxn];
int vis[maxn];
int in[maxn];
int used[maxn];
int ans ;
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;
void dfs(int u,int fa)
{
int len = G[u].size();
for(int i=0;i<len;i++)
{
int v = G[u][i];
dfs(v,u);
}
if(!vis[u]&&!vis[fa])
{
ans ++; vis[u] = 1; vis[fa] = 1;
}
}
int main()
{
int cases;
read(cases);
while(cases--)
{
read(n); read(k);
for(int i=0;i<=n;i++) G[i].clear(); ans = 0;
for(int i=2;i<=n;i++)
{
read(a);
G[a].push_back(i);
}
G[0].push_back(1);
memset(vis,0,sizeof(vis));
dfs(1,-1);
if(vis[0]) ans--;
if(ans*2>=k) printf("%d\n",(k+1)/2);
else printf("%d\n",ans+(k-2*ans));
}
return 0;
}
//7 7
//1 2 6 6 2 4