[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;
}

posted @ 2018-12-23 13:55  daniel14311531  阅读(188)  评论(0编辑  收藏  举报