1. 程式人生 > >【題解】codeforces1029E[Codeforces Round #506 (Div. 3)]E.Tree with Small Distances 優先佇列+dfs

【題解】codeforces1029E[Codeforces Round #506 (Div. 3)]E.Tree with Small Distances 優先佇列+dfs

題目連結

Description

You are given an undirected tree consisting of nn vertices. An undirected tree is a connected undirected graph with n1n−1 edges.

Your task is to add the minimum number of edges in such a way that the length of the shortest path from the vertex 11 to any other vertex is at most 2

2. Note that you are not allowed to add loops and multiple edges.

Input

The first line contains one integer nn (2n2×105)(2≤n≤2\times10^5) — the number of vertices in the tree.

The following n1n−1 lines contain edges: edge ii is given as a pair of vertices ui,viu_i,v_i (1ui,v

in)(1≤ui,vi≤n). It is guaranteed that the given edges form a tree. It is guaranteed that there are no loops and multiple edges in the given edges.

Output

Print a single integer — the minimum number of edges you have to add in order to make the shortest distance from the vertex 11 to any other vertex at most 2

2. Note that you are not allowed to add loops and multiple edges.

Examples

Input

7 1 2 2 3 2 4 4 5 4 6 5 7

Output

2

Input

7 1 2 1 3 2 4 2 5 3 6 1 7

Output

0

Input

7 1 2 2 3 3 4 3 5 3 6 3 7

Output

1

Note

The tree corresponding to the first example: 在這裡插入圖片描述 The answer is 22, some of the possible answers are the following: [(1,5),(1,6)],[(1,4),(1,7)],[(1,6),(1,7)][(1,5),(1,6)], [(1,4),(1,7)], [(1,6),(1,7)].

The tree corresponding to the second example: 在這裡插入圖片描述 The answer is 00.

The tree corresponding to the third example: 在這裡插入圖片描述 The answer is 11, only one possible way to reach it is to add the edge (1,3)(1,3).

要求連最少的邊使以 11 為根的樹上所有子節點深度不超過 22dfsdfs 一遍求出每個點的深度,把每個深度超過 22 的點加入堆中。每次取出堆頂節點,如果沒有被更新,就向他的父節點連一條返祖邊,然後遍歷與父節點直接相連的節點標記。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=2e5+10;
int dep[N],fa[N],n,hd[N],tot,vis[N];
struct Edge{
	int v,nx;
}e[N<<1];
void add(int u,int v)
{
	e[tot].v=v;
	e[tot].nx=hd[u];
	hd[u]=tot++;
}
void dfs(int u,int f)
{
	for(int i=hd[u];~i;i=e[i].nx)
	{
		int v=e[i].v;
		if(v==f)continue;
		fa[v]=u;dep[v]=dep[u]+1;
		dfs(v,u);
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	memset(hd,-1,sizeof(hd));
	scanf("%d",&n);
	int u,v,ans=0;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	dfs(1,0);
	priority_queue<pair<int,int> >q;
	for(int i=1;i<=n;i++)if(dep[i]>2)q.push(make_pair(dep[i],i));
	while(q.size())
	{
		u=q.top().second;q.pop();
		if(vis[u])continue;
		ans++;vis[fa[u]]=1;
		for(int i=hd[fa[u]];~i;i=e[i].nx)vis[e[i].v]=1;
	}
	printf("%d\n",ans);
	return 0;
}

總結

可能可以證明每次去最深的節點是最優的,反例是容易舉出的。