欢迎来爆踩我~|

AFewSuns

园龄:4年11个月粉丝:42关注:3

CF1039D You Are Given a Tree

题目传送门

题目大意

给出一棵n个节点的树,对于1~n间的每一个数k,你需要求出: 最多能选出多少条互不相交的路径,使得每条路径的长度都为k

思路

首先思考暴力的做法。就是贪心+树形dp,把整个树dfs一次,对于每个节点考虑它子节点的最长链和次长链。如果最长链+次长链+1k,那么就说明它子节点的最长链和次长链通过那个子节点连起来形成的链可以满足长度大于等于k,答案+1

那么为什么满足条件就一定要先把它们连起来呢?因为由于当前存在了一条满足要求的链,如果不计入答案,把最长链往上传,那么最多对答案也只有1的贡献。所以先连起来可能会更优。这样时间复杂度就是O(n2)

之后就用分治优化。设分治节点为t,对于第一段直接用暴力求解,时间复杂度就是O(nt),对于第二段,因为答案只会在0~nt这个范围内,而且是单调不升的,相同答案的k值肯定是连在一起的,所以可以考虑从左往右扫一遍,每次用二分出答案相同的一段,这样时间最多也就n2log(n)t 。所以当t取nlog(n)时,时间复杂度最小,为O(nnlog(n))

当然,tn会更容易理解,虽然时间没有t=n2log(n)t 快,但只要我们优化一下,去掉dfs的过程,记录dfs序,通过for循环以达到dfs的目的,也是可以过的。

所以我也把这个小优化也加到了我的代码里。

代码

复制代码
#include<bits/stdc++.h>
using namespace std;
int n,q,x,y,head[200002],Fa[100001],dfsx[100001],f[100001],cnt=0,tot=0,t,l,r,mid;
struct node{
    int nxt,to;
}e[200002];
void add(int x,int y){
    e[++cnt].nxt=head[x];
    e[cnt].to=y;
    head[x]=cnt;
}
void dfs(int x,int fa){
    Fa[x]=fa;
    for(int i=head[x];i;i=e[i].nxt){
        int v=e[i].to;
        if(v!=fa) dfs(v,x);
    }
    dfsx[++tot]=x;
    return;
}
int solve(int x){
    int k,ans=0;
    for(int i=1;i<=n;i++) f[i]=1;
    for(int i=1;i<=n;i++){
        int k=dfsx[i];
        if(Fa[k]&&~f[Fa[k]]&&~f[k]){
            if(f[k]+f[Fa[k]]>=x){
                f[Fa[k]]=-1;
                ans++;
            }
            else f[Fa[k]]=max(f[Fa[k]],f[k]+1);
        }
    }
    return ans;
}
int main(){
    scanf("%d",&n);
    q=sqrt(n*log(n)/log(2));
    for(int i=1;i<n;i++){
        scanf("%d %d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(1,0);
    printf("%d\n",n);
    for(int i=2;i<=q;i++) printf("%d\n",solve(i));
    for(int i=q+1;i<=n;i=l+1){
        l=i;
        r=n;
        t=solve(i);
        while(l<r){
            mid=(l+r+1)>>1;
            if(solve(mid)==t) l=mid;
            else r=mid-1;
        }
        for(int j=i;j<=l;j++) printf("%d\n",t);
    }
    return 0;
}
请不要随意抄代码!
复制代码

 

不要忘记点个赞哦

 

完结撒花

 

本文作者:AFewSuns

本文链接:https://www.cnblogs.com/AFewSuns/p/12623769.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   AFewSuns  阅读(218)  评论(10编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起