首页 > 其他 > 详细

FZOJ 3602 T2

时间:2020-07-23 01:58:29      阅读:80      评论:0      收藏:0      [点我收藏+]

对最外层所有叶子编号(编号都为 \(1\)),然后把他们删去,然后给倒数第二层叶子编号(编号都为 \(2\))。以此类推。

对于每一种编号考虑,由于一条路径最多只能覆盖两个编号相同的节点,所以最后答案为 \(\sum\limits_{i=1}^{k}\max(2\times L,sum[i])\)。其中 \(k\) 为叶子总层数,\(sum[i]\) 表示一种编号的点有多少个。

显然这个式子是答案的上界,至于为什么能取到也可以证明(但我不会,所以说这是结论题)。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>

using namespace std;

const int N=1000009;
int n,head[N],cnt,deg[N],L,del[N],ans;
queue <int> q;
struct Edge
{
	int nxt,to;
}g[N*2];

void add(int from,int to)
{
	g[++cnt].nxt=head[from];
	g[cnt].to=to;
	head[from]=cnt;
}

void init()
{
	scanf("%d %d",&n,&L);
	for (int i=1,x,y;i<n;i++)
		scanf("%d %d",&x,&y),
		add(x,y),add(y,x),deg[x]++,deg[y]++;
}

void work()
{
	for (int i=1;i<=n;i++)
		if(deg[i]==1)
			q.push(i),del[i]=1;
	int last=q.size();
	ans+=min(2*L,(int)q.size());
	while(!q.empty())
	{
		int x=q.front();q.pop();
		last--,del[x]=1;
		for (int i=head[x];i;i=g[i].nxt)
		{
			int v=g[i].to;
			if(del[v]) continue;
			deg[v]--;
			if(deg[v]==1)
				q.push(v);
		}
		if(!last) last=q.size(),ans+=min(2*L,(int)q.size());
	}
	printf("%d\n",ans);
}

int main()
{
	init();
	work();
	return 0;
}

FZOJ 3602 T2

原文:https://www.cnblogs.com/With-penguin/p/13363848.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!