F. Programming Competition

BerSoft is the biggest IT corporation in Berland. There are n n n employees at BerSoft company, numbered from 1 1 1 to n n n.

The first employee is the head of the company, and he does not have any superiors. Every other employee i i i has exactly one direct superior p i p_i pi.

Employee x x x is considered to be a superior (direct or indirect) of employee y y y if one of the following conditions holds:

  • employee x x x is the direct superior of employee y y y;
  • employee x x x is a superior of the direct superior of employee y y y.

The structure of BerSoft is organized in such a way that the head of the company is superior of every employee.

A programming competition is going to be held soon. Two-person teams should be created for this purpose. However, if one employee in a team is the superior of another, they are uncomfortable together. So, teams of two people should be created so that no one is the superior of the other. Note that no employee can participate in more than one team.

Your task is to calculate the maximum possible number of teams according to the aforementioned rules.
Input

The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1t104) — the number of test cases.

The first line of each test case contains a single integer n n n ( 2 ≤ n ≤ 2 ⋅ 1 0 5 2 \le n \le 2 \cdot 10^5 2n2105) — the number of employees.

The second line contains n − 1 n-1 n1 integers p 2 , p 3 , … , p n p_2, p_3, \dots, p_n p2,p3,,pn ( 1 ≤ p i ≤ n 1 \le p_i \le n 1pin), where p i p_i pi is the index of the direct superior of the i i i-th employee.

The sum of n n n over all test cases doesn’t exceed 2 ⋅ 1 0 5 2 \cdot 10^5 2105.
Output

For each test case, print a single integer — the maximum possible number of teams according to the aforementioned rules.
贪心+树形dp

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, M = 4e5 + 10;
int h[N], e[M], ne[M], idx;
int sz[N];
void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void init(int u)
{
	sz[u] = 1;
	for (int i = h[u]; ~i; i = ne[i]) {
		int v = e[i];
        init(v);
		sz[u] += sz[v];
	}
}
int dfs(int u, int k)
{
	int tot = 0, mx = -1;
	for (int i = h[u]; ~i; i = ne[i])
	{
		int v = e[i];
		tot += sz[v];
		if (mx == -1 || sz[mx] < sz[v])mx = v;
	}
	if (tot == 0)return 0;
	if (sz[mx] - k <= tot - sz[mx])
		return (tot - k) / 2;
	int add = tot - sz[mx];
	return add + dfs(mx, max(0, add + k - 1));
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		memset(h, -1, sizeof h);
		idx = 0;
		for (int i = 2; i <= n; i++)
		{
			int p;
			cin >> p;
			add(p, i);
		}
		init(1);
		cout << dfs(1, 0) << endl;
	}
}
  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值