Description
给定一棵树。要求往树中加入一些边使得从1到其他节点的距离至多是2 。 输出加入边的最小数量。(边全部都是无向的)
Input
第一行一个整数n,表示树中的节点个数。 接下来n−1行,每行两个整数x,y,表示x,y之间有一条连边。
Output
输出一个整数,表示加入边的最小数量。
贪心做法,
我们每次选择深度最深的点,向其父节点加边来标记其他点。(到达这些点的距离都不超过(2).)
为什么向其父亲节点加边?因为这样会覆盖比较多的点。
如果遇到被标记的点,就(continue).
不太会证明正确性,但是可行。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
#define R register
using namespace std;
const int gz=2e5+8;
inline void in(R int &x)
{
R int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int head[gz],tot,depth[gz],ans,n,f[gz],cnt;
bool ok[gz];
struct cod{int u,v;}edge[gz<<1];
inline void add(R int x,R int y)
{
edge[++tot].u=head[x];
edge[tot].v=y;
head[x]=tot;
}
struct hop
{
int u,dep;
bool operator <(const hop&a)const
{
return dep>a.dep;
}
}q[gz];
void dfs(R int u,R int fa)
{
depth[u]=depth[fa]+1;f[u]=fa;
if(depth[u]>2)q[++cnt].u=u,q[cnt].dep=depth[u];
for(R int i=head[u];i;i=edge[i].u)
{
if(edge[i].v==fa)continue;
dfs(edge[i].v,u);
}
}
int main()
{
in(n);
for(R int i=1,x,y;i<n;i++)
{
in(x),in(y);
add(x,y),add(y,x);
}
depth[0]=-1;
dfs(1,0);
sort(q+1,q+cnt+1);
for(R int j=1;j<=cnt;j++)
{
R int u=q[j].u;
if(ok[u])continue;
u=f[u];
ok[u]=true;
for(R int i=head[u];i;i=edge[i].u)
ok[edge[i].v]=true;
ans++;
}
printf("%d",ans);
}