zoukankan      html  css  js  c++  java
  • 【CF 1039D|GOJ 3502】You Are Given a Tree

    传送门

    1. http://u.gdfzoj.com/problem/3502
    2. https://codeforces.com/problemset/problem/1039/D

    题意简述

    给出 (1)(n)个节点的树,对于 ([l,r]) 间的每 (1) 个数 (k),你需要求出:最多能选出多少条互不相交的路径,每条路径的长度都为 (k)

    解析

    一开始假设 (k) 是确定的,我们可以考虑暴力。不妨设 (f_x) 为以 (x) 为根中最长链的长度。转移方式就是能合并就合并,反之选一条最长的链向上延伸,每一次时间复杂度为 (O(n))

    通过玄学的计算我们可以发现 (klesqrt{n}) 的时候答案最多只有 (sqrt{n}) 种取值,(k>sqrt{n}) 也一样。并且答案大小的具有单调性(这十分显然,链越长答案越少)。于是我们直接二分边界,统计答案即可,复杂度为(O(nsqrt{n}log_2n))

    我这里用的是别的方法整体二分,复杂度一样(好写一些)。

    Code:

    #include<bits/stdc++.h>
    namespace mystd {
    	using namespace std;
    #define LL long long
    	inline LL read() {
    		char c=getchar();
    		LL sum=0;
    		while(c<'0'||c>'9') {
    			c=getchar();
    		}
    		while(c>='0'&&c<='9') {
    			sum=(sum<<3)-'0'+(sum<<1)+c,c=getchar();
    		}
    		return sum;
    	}
    	inline void write(LL x) {
    		if(x>9) {
    			write(x/10);
    		}
    		putchar(x%10+'0');
    	}
    	const int d[4][2]= {
    		{1,0},{0,1},{-1,0},{0,-1}
    	},mod=998244353,N=1e5+5;
    }
    using namespace Bu_Yao_Tian_Tian_Bi_Sai;
    struct edge {
    	int to,nxt;
    } e[N<<1];
    int cnt,head[N];
    void add(int u,int v) {
    	e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;
    }
    int n=read(),ans[N],f[N];
    void dp(int u,int fa,int len) {
    	f[u]=0;
    	int maxn=0,sec=0;
    	for(int i=head[u]; i; i=e[i].nxt) {
    		int v=e[i].to;
    		if(v==fa) {
    			continue ;
    		}
    		dp(v,u,len);
    		if(f[v]>=maxn) {
    			sec=maxn,maxn=f[v];
    		} else {
    			sec=max(sec,f[v]);
    		}
    	}
    	if(sec+maxn+1>=len) {
    		cnt++;
    	} else {
    		f[u]=maxn+1;
    	}
    }
    void fen(int st,int nd,int l,int r) {
    	if(st>nd||l>r) {
    		return ;
    	}
    	if(l==r) {
    		for(int i=st; i<=nd; i++) {
    			ans[i]=l;
    		}
    		return ;
    	}
    	int mid=(st+nd)>>1;
    	cnt=0;
    	dp(1,0,mid);
    	ans[mid]=cnt;
    	fen(st,mid-1,cnt,r),fen(mid+1,nd,l,cnt);
    }
    int main() {
    	for(int i=1,u,v; i<n; i++) {
    		u=read(),v=read(),add(u,v),add(v,u);
    	}
    	fen(1,n,0,n);
    	for(int i=1; i<=n; i++) {
    		write(ans[i]),putchar(' ');
    	}
    	return 0;
    }
    

    完美撒花~

    知识共享许可协议

    本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

    限于本人水平,如果文章有表述不当之处,还请不吝赐教。

  • 相关阅读:
    angular多个控制器如何共享数据
    $q服务的使用
    $sanitize和$sce服务的使用方法
    json对象与json字符串互转方法
    css语法和JS语法的对比
    让低版本IE也能正常运行HTML5+CSS3网站的3种解决方案
    HTML中的IE条件注释
    区块链是什么,如何评价区块链
    编写Python脚本把sqlAlchemy对象转换成dict的教程
    编写Python脚本把sqlAlchemy对象转换成dict的教程
  • 原文地址:https://www.cnblogs.com/Sam2007/p/12782448.html
Copyright © 2011-2022 走看看