AGC001 C Shorten Diameter(dfs)
AGC001 C Shorten Diameter
本题不难,不至于紫(
解题思路
看到 \(n\leq 2000\) 就知道是 \(O(n^2)\) 没得跑了。关键如何 \(O(n^2)\)。
我们可以对 \(k\) 进行分类。
如果 \(k\) 为偶数,那么我们知道我们删点过后得到的树的直径一定有一个中心点 \(u\),为了使得直径为 \(k\),那么距离 \(u\) 距离大于 \(\frac {n}2\) 的点必须删除。我们枚举 \(u\),然后 dfs 即可。
如果 \(k\) 为奇数,和上面类似的,我们可以枚举中心边,也是一样 dfs 一下就可以知道答案了。取最小值即可。
代码
代码很短
//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
using namespace std;
int read() {
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
char read_char() {
char ch=getchar();
while(!isalpha(ch)) {
ch=getchar();
}
return ch;
}
const int MAXN=20000+10;
int n,cnt,k,ans,m,tot;
int h[MAXN],sz[MAXN],dis[MAXN];
struct edge {
int v,nxt;
}e[MAXN<<1];
void addedge(int u,int v) {
e[++cnt].nxt=h[u];
e[cnt].v=v;
h[u]=cnt;
}
void insert(int u,int v) {
addedge(u,v);
addedge(v,u);
}
void dfs1(int u,int fa) {
dis[u]=dis[fa]+1;
if(dis[u]-1>k/2) {
tot++;
}
for(int i=h[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa) {
dfs1(v,u);
}
}
}
int main() {
cin>>n>>k;
for(int i=1;i<n;i++) {
insert(read(),read());
}
ans=1e9+10;
if(k&1) {
for(int u=1;u<=n;u++) {
for(int i=h[u];i;i=e[i].nxt) {
int v=e[i].v;
dis[v]=0;
dfs1(u,v);
dis[u]=0;
dfs1(v,u);
ans=min(ans,tot);
tot=0;
}
}
}
else {
for(int i=1;i<=n;i++) {
dfs1(i,0);
ans=min(ans,tot);
tot=0;
}
}
cout<<ans<<endl;
return 0;
}