题目:E. Tree with Small Distances
题意
给出一颗具有n个顶点的无向树,增加最小的边数量,使从根结点1到任意顶点的最短路径长度不超过2.
题解
先用树形dp求出每个结点到根结点1的路径长度,最后按路径长度从大到小排序,将路径长度大于2的结点的父节点与根结点相连,修改次数则加一,最后求出修改总次数。
ac代码:
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
#define M_PI 3.14159265358979323846
int siz[200005],pre[200005];
int ans=0,tot=0;
struct node{
int v,l;
}b[200005];
int cmp(node x,node y)
{
return x.l>y.l;
}
vector<int>a[200005];
void dfs(int u,int fa)
{
pre[u]=fa;
for(auto t:a[u])
{
int v=t;
if(v==fa) continue;
siz[v]+=siz[u]+1;
if(siz[v]>2) b[++tot].l=siz[v],b[tot].v=v;
dfs(v,u);
}
}
void update(int u)
{
siz[u]=1;
ans++;
for(auto t:a[u])
{
int v=t;
siz[v]=2;
}
}
void solve()
{
for(int i=1;i<=tot;i++)
{
if(siz[b[i].v]<=2) continue;
update(pre[b[i].v]);
}
}
int main()
{
ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
siz[i]=0;
a[i].clear();
}
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
dfs(1,1);
sort(b+1,b+1+tot,cmp);
solve();
cout<<ans<<endl;
return 0;
}