• FZOJ 3602 T2


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

    对于每一种编号考虑,由于一条路径最多只能覆盖两个编号相同的节点,所以最后答案为 (sumlimits_{i=1}^{k}max(2 imes 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
    ",ans);
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    java正则表达式(九)
    java正则表达式(八)
    java正则表达式(十)
    正确理解ThreadLocal
    Class.getResource与ClassLoader.getResource()区别
    seajs中define方法的id和dependencies参数
    seajs研究一二三
    十八年开发经验分享(三)问题解决篇(中)
    EntityModelStudio系列教程4静态建模进阶
    EntityModelStudio系列教程6EMLib框架之Orm
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13363848.html
Copyright © 2020-2023  润新知