AGC001 C - Shorten Diameter
AGC的题目果然都牛逼啊
像我这种智力不够的人完全做不动啊
这题考虑K是奇偶不同的情况
K为偶数枚举每一个点作为直径的中点(中心)
K为奇数,枚举每条边作为直径中间边
然后往下K/2层,>K/2层的都扔掉即可
因为中心到直径两端相同,所以必须<=K/2
代码如下:
#include<bits/stdc++.h> #define N 500005 using namespace std; int n,K,x,y,kk,ans,tot,opt,head[N]; struct Tree{int nxt,to,from;}e[N]; inline void link(int x,int y){e[++kk].nxt=head[x];e[kk].from=x;e[kk].to=y;head[x]=kk;} void dfs(int u,int fa,int dep){ if (dep>K) return;tot++; for (int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if (v==fa) continue; dfs(v,u,dep+1); } } inline void solve(int x){ tot=0; dfs(x,-1,0); ans=min(ans,n-tot); } inline void solve1(int x){ tot=0;dfs(e[x].to,e[x].from,0); dfs(e[x].from,e[x].to,0); ans=min(ans,n-tot); } int main(){ scanf("%d%d",&n,&K); int opt=(K&1); if (K%2==0) K/=2; else K=(K-1)/2; for (int i=1;i<n;i++){ scanf("%d%d",&x,&y); link(x,y);link(y,x); } ans=1e9; if (!opt) for (int i=1;i<=n;i++) solve(i); if (opt) for (int i=1;i<=kk;i+=2) solve1(i); printf("%d\n",ans); return 0; }