[POI2006]MET-Subway - 解题报告
题意:给定一棵树,选择l条路径覆盖最多的点的个数是多少。
($n \leq 1000000 $)
题解:首先根据数据范围,得知时间复杂度O(\(n\))。
满足一个贪心,即从叶子节点取最优,每次取路径最长的两个点。
用拓扑排序得到每个深度点数,显然这一层要么取 $ l \times 2 $ 个点,要么全部去完。
(好妙啊)
代码:
#include<bits/stdc++.h>
using namespace std;
int n,k,In[1000010],dep[1000010],tot[1000010],ans=0;
int cnt=0,hed[1000010],to[2000010],nxt[2000010];
bool vis[1000010];
int q[1000010],f=1,e=0;
inline void add(int x,int y) { to[++cnt]=y,nxt[cnt]=hed[x],hed[x]=cnt; }
inline int Min(int x,int y) { return x<y? x:y; }
int main() {
scanf("%d%d",&n,&k);
for(int i=1,x,y;i<n;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x),++In[x],++In[y];
for(int i=1;i<=n;i++)
if(In[i]==1) vis[i]=1,q[++e]=i,++tot[dep[i]=1];
while(f<=e) {
int u=q[f++];
for(int i=hed[u];i;i=nxt[i]) {
if(vis[to[i]]) continue;
if((--In[to[i]])==1)
vis[to[i]]=1,++tot[dep[to[i]]=dep[u]+1],q[++e]=to[i];
}
}
for(int i=1;tot[i];i++) ans+=Min(k*2,tot[i]);
printf("%d\n",ans);
return 0;
}