[dfs][思维]Infected Tree CF1689C

59 篇文章 0 订阅
10 篇文章 0 订阅

Byteland is a beautiful land known because of its beautiful trees.

Misha has found a binary tree with nn vertices, numbered from 11 to nn. A binary tree is an acyclic connected bidirectional graph containing nn vertices and n−1n−1 edges. Each vertex has a degree at most 33, whereas the root is the vertex with the number 11 and it has a degree at most 22.

Unfortunately, the root got infected.

The following process happens nn times:

  • Misha either chooses a non-infected (and not deleted) vertex and deletes it with all edges which have an end in this vertex or just does nothing.
  • Then, the infection spreads to each vertex that is connected by an edge to an already infected vertex (all already infected vertices remain infected).

As Misha does not have much time to think, please tell him what is the maximum number of vertices he can save from the infection (note that deleted vertices are not counted as saved).

Input

There are several test cases in the input data. The first line contains a single integer tt (1≤t≤50001≤t≤5000) — the number of test cases. This is followed by the test cases description.

The first line of each test case contains one integer nn (2≤n≤3⋅1052≤n≤3⋅105) — the number of vertices of the tree.

The ii-th of the following n−1n−1 lines in the test case contains two positive integers uiui and vivi (1≤ui,vi≤n1≤ui,vi≤n), meaning that there exists an edge between them in the graph.

It is guaranteed that the graph is a binary tree rooted at 11. It is also guaranteed that the sum of nn over all test cases won't exceed 3⋅1053⋅105.

Output

For each test case, output the maximum number of vertices Misha can save.

Example

input

4
2
1 2
4
1 2
2 3
2 4
7
1 2
1 5
2 3
2 4
5 6
5 7
15
1 2
2 3
3 4
4 5
4 6
3 7
2 8
1 9
9 10
9 11
10 12
10 13
11 14
11 15

output

0
2
2
10

Note

In the first test case, the only possible action is to delete vertex 22, after which we save 00 vertices in total.

In the second test case, if we delete vertex 22, we can save vertices 33 and 44.

题意: 给出一棵含有n个结点的二叉树,初始根节点感染了病毒,接下来会执行若干次操作,每次操作删除一个未被感染的点及其连边,然后病毒向下扩散一层,当病毒无法蔓延时就停止操作,求最终未被感染且未被删除的最大结点个数。

分析: 先说一下一开始想到的错误思路,先求出每个结点的子结点数量,对于每个结点当要删除时优先删子结点个数多的那个结点,这样能保证本次操作是最优的,但是局部最优并不能推出全局最优,并且当两结点的子结点个数相同时该删哪个也是个问题,实际上病毒蔓延的路径就是一条dfs的路径,通过删除结点我们是可以控制蔓延路径的,显然我们希望这条路径越短越好,所以应该找到距离根最近的叶子结点,因为病毒蔓延终止于叶子,但是还需要注意的是病毒蔓延还会终止于单分支结点,当走到一个单分支结点时可以通过删除其子结点来终止蔓延,所以还要找到距离根最近的单分支结点,那么具体要引到单分支结点还是叶子结点呢?对于两种情况都求一下,然后取一个最大值就好了。设最近的叶子结点距离根为d1,那么过程中会有2*d1-1个结点被感染或删除,若换成单分支结点,那就会有2*d2个结点被感染或删除,这点画图就能看出来,所以最终答案就是max(n-(2*d1-1), n-2*d2)。

具体代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;

vector<int> g[300005];
int d0, d1, ans; 

void dfs1(int now, int fa, int step){
	if(g[now].size() == 2 && fa != 0)
		d1 = min(d1, step);
	else if(g[now].size() == 1 && fa == 0)
		d1 = min(d1, step);
	if(g[now].size() == 1 && fa != 0)
		d0 = min(d0, step);
	else if(g[now].size() == 0 && fa == 0)
		d0 = min(d0, step);
	for(int i = 0; i < g[now].size(); i++){
		int to = g[now][i];
		if(to == fa) continue;
		dfs1(to, now, step+1);
	}
}

signed main()
{
	int T;
	cin >> T;
	while(T--){
		int n;
		scanf("%d", &n);
		for(int i = 1; i <= n; i++)
			g[i].clear();
		for(int i = 1; i < n; i++){
			int u, v;
			scanf("%d%d", &u, &v);
			g[u].push_back(v);
			g[v].push_back(u);
		}
		d0 = d1 = inf;
		dfs1(1, 0, 1);
		int ans = max(n-(2*d0-1), n-2*d1);	
		printf("%d\n", ans);
	}
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值