zoukankan      html  css  js  c++  java
  • [CF1039D] You Are Given a Tree

    问题简述

    有一棵n个节点的树
    其中一个简单路径的集合被称为k合法当且仅当:
    树的每个节点至多属于其中一条路径,且每条路径恰好包含k个点
    对于k∈[1,n],求出k合法路径集合的最多路径数
    即:设k合法路径集合为S,求最大的|S|

    样例输入

    6
    1 2
    2 3
    2 4
    1 5
    5 6

    样例输出

    6
    2
    2
    1
    1
    0

    说明

    样例如下

    img

    解析

    首先,(O(n^2))的暴力做法可以用贪心,对于每一棵子树,能够在子树内拼成长度为k的链就拼,返回剩下的最长的链到父节点去继续拼。

    考虑如何优化。这里用到了根号分治的方法,当k小于等于(sqrt n)的时候,就直接暴力去做;当k大于(sqrt n)时,可以发现对于某一段连续的k,答案是一样的,所以我们二分出这个一样的区间,然后把这个区间的答案都赋为当前的答案。具体实现可以参考代码。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #define N 100002
    using namespace std;
    int head[N],ver[N*2],nxt[N*2],l;
    int n,i,j,f[N],ans[N],top,s[N],fa[N];
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    void insert(int x,int y)
    {
    	l++;
    	ver[l]=y;
    	nxt[l]=head[x];
    	head[x]=l;
    }
    void dfs(int x,int pre)
    {
    	fa[x]=pre;
    	for(int i=head[x];i;i=nxt[i]){
    		int y=ver[i];
    		if(y!=pre) dfs(y,x);
    	}
    	s[++top]=x;
    }
    int dp(int k)
    {
    	int ans=0,f[N];
    	f[0]=-1;
    	for(int i=1;i<=n;i++) f[i]=1;
    	for(int i=1;i<=n;i++){
    		int x=s[i];
    		if(f[x]!=-1&&f[fa[x]]!=-1){
    			if(f[x]+f[fa[x]]>=k){
    				ans++;
    				f[fa[x]]=-1;
    			}
    			else f[fa[x]]=max(f[fa[x]],f[x]+1);
    		}
    	}
    	return ans;
    }
    int main()
    {
    	n=read();
    	for(i=1;i<n;i++){
    		int u=read(),v=read();
    		insert(u,v);
    		insert(v,u);
    	}
    	dfs(1,0);
    	int m=sqrt(n*log2(n)),l,r,mid,tmp;
    	ans[1]=n;
    	for(i=2;i<=m;i++) ans[i]=dp(i);
    	for(i=m+1;i<=n;i=l+1){
    		l=i,r=n;
    		tmp=dp(i);
    		while(l<r){
    			mid=(l+r+1)/2;
    			if(dp(mid)==tmp) l=mid;
    			else r=mid-1;
    		}
    		for(j=i;j<=l;j++) ans[j]=tmp;
    	}
    	for(i=1;i<=n;i++) printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Centos7创建CA和申请证书 转自https://www.cnblogs.com/mingzhang/p/8949541.html
    go-micro介绍 摘自https://www.cnblogs.com/s0-0s/p/6874800.html
    docker centos7创建consul镜像以及用docker-compose启动镜像
    今天想用jquery来实现div的拖放功能
    canvas
    子元素的div不继承父元素的透明度
    BOM
    DOM
    JS的循环、复杂运算符
    梳理一下JS的基本语法
  • 原文地址:https://www.cnblogs.com/LSlzf/p/11878448.html
Copyright © 2011-2022 走看看