https://atcoder.jp/contests/agc001/tasks/agc001_c
很经典的模型了,感觉今年打的训练赛都见过两次。。。果然AGC的题目都挺经典的
要让整棵树直径<=k,然后又要删掉的点最少,那么就是枚举直径的中心,让直径<=k且点最多
发现n=2000,可以n^2做,那么就枚举每个点为直径中心,然后规定长度小于k/2,看最多能有多少点
然后以每条边为直径中心,从这条边两个点向外跑(k-1)/2,看最多有多少点
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
int n,m,cnt,tot,cas,ans,k,mx;
int a[maxl];
bool vis[maxl];
char s[maxl];
vector<int> e[maxl];
struct ed
{
int u,v;
}g[maxl];
inline void prework()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&g[i].u,&g[i].v);
e[g[i].u].push_back(g[i].v);
e[g[i].v].push_back(g[i].u);
}
}
inline void dfs(int u,int fa,int dis,int len)
{
tot++;
if(dis==len)
return;
for(int v:e[u])
if(v!=fa)
dfs(v,u,dis+1,len);
}
inline void mainwork()
{
mx=0;
for(int i=1;i<=n;i++)
{
tot=0;
dfs(i,0,0,k/2);
mx=max(tot,mx);
}
for(int i=1;i<=n-1;i++)
{
tot=0;
dfs(g[i].u,g[i].v,0,(k-1)/2);
dfs(g[i].v,g[i].u,0,(k-1)/2);
mx=max(tot,mx);
}
}
inline void print()
{
printf("%d",n-mx);
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}