【題解】codeforces1029E[Codeforces Round #506 (Div. 3)]E.Tree with Small Distances 優先佇列+dfs
Description
You are given an undirected tree consisting of vertices. An undirected tree is a connected undirected graph with 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 to any other vertex is at most . Note that you are not allowed to add loops and multiple edges.
Input
The first line contains one integer — the number of vertices in the tree.
The following lines contain edges: edge is given as a pair of vertices . 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 to any other vertex at most . 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 , some of the possible answers are the following: .
The tree corresponding to the second example: The answer is .
The tree corresponding to the third example: The answer is , only one possible way to reach it is to add the edge .
要求連最少的邊使以 為根的樹上所有子節點深度不超過 。 一遍求出每個點的深度,把每個深度超過 的點加入堆中。每次取出堆頂節點,如果沒有被更新,就向他的父節點連一條返祖邊,然後遍歷與父節點直接相連的節點標記。
#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;
}
總結
可能可以證明每次去最深的節點是最優的,反例是容易舉出的。