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;
}
posted @ 2022-09-04 14:41  huayucaiji  阅读(20)  评论(0编辑  收藏  举报