P3441-[POI2006]MET-Subway【图论,贪心】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/89067984

正题

题目链接:https://www.luogu.org/problemnew/show/P3441


题目大意

I I 条路径最多可以覆盖树上多少个点。


解题思路

我们先只考虑叶子节点,显然可以覆盖 m i n { n u m , I 2 } min\{num_叶,I*2\}
然后网上递推,发现依旧是 m i n { n u m i , I 2 } min\{num_i,I*2\}
拓扑求出每个 n u m num


c o d e code

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e6+10;
int n,m,f[N],death,ls[N],tot,ans,dep[N],in[N];
queue<int> q;
struct edge{
	int to,next;
}a[2*N];
void addl(int x,int y)
{
	a[++tot].to=y;
	a[tot].next=ls[x];
	ls[x]=tot;
	in[y]++;
}
void topsort()
{
	for(int i=1;i<=n;i++)
	  if(in[i]==1){
	  	  dep[i]=1;
	  	  f[1]++;
	  	  q.push(i);
	  }
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=ls[x];i;i=a[i].next)
		{
			int y=a[i].to;
			if(dep[y]) continue;
			if((--in[y])==1){
				dep[y]=dep[x]+1;
				q.push(y);
				f[dep[y]]++;
				death=max(death,dep[y]);
			}
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		addl(x,y);addl(y,x);
	}
	topsort();
	for(int i=1;i<=death;i++)
	  ans+=min(2*m,f[i]);
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/89067984