【jzoj4715】【树上路径】【树】【分治】【点分治】

本文介绍了一种解决特定树形结构问题的方法——点分治。通过计算树中所有节点到重心的距离及其所属子树,并对这些距离进行排序,利用不同子树间的点更新答案,寻找满足条件的最小k值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

给出一棵树,求出最小的k,使得,且在树中存在路径p,使得k>=S且k<=E。(k为路径p上的边的权值和)

解题思路

点分治,求出所有点到当前重心的距离以及所属的子树,排序后扫描并用不同子树的点更新答案,然而我的做法很暴力,很有可能超时,但随机数据下表现良好,应该有更好的方法。

暴力code

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const maxn=100000,inf=2147483647;
int n,s,e,gra,lim,to[maxn*2+10],len[maxn*2+10],next[maxn*2+10],begin[maxn+10],tag[maxn+10],v[maxn+10],size[maxn+10],dis[maxn+10],ans=inf;
bool done[maxn+10];
void insert(int u,int v,int w){
    to[++gra]=v;
    len[gra]=w;
    next[gra]=begin[u];
    begin[u]=gra;
}
void getsize(int now,int pre){
    size[now]=1;
    for(int i=begin[now];i;i=next[i])
        if((to[i]!=pre)&&(!done[to[i]])){
            getsize(to[i],now);
            size[now]+=size[to[i]];
        }
}
int dfsss(int now,int rsize,int pre){
    for(int i=begin[now];i;i=next[i])
        if((to[i]!=pre)&&(!done[to[i]])){
            int tmp=dfsss(to[i],rsize,now);
            if(size[tmp]>=rsize/2)return tmp;
        }
    return now;
}
int root(int now){
    getsize(now,0);
    return dfsss(now,size[now],0);
}
void dfss(int now,int pre,int rot,int sum){
    dis[++dis[0]]=sum;
    tag[dis[0]]=rot;
    for(int i=begin[now];i;i=next[i])
        if((to[i]!=pre)&&(!done[to[i]]))
            dfss(to[i],now,rot,sum+len[i]);
}
bool cmp(int i,int j){
    return (dis[i]<dis[j])||((dis[i]==dis[j])&&(i<j));
}
int dfs(int now){
    done[now]=1;
    dis[dis[0]=1]=0;
    tag[1]=0;
    for(int i=begin[now];i;i=next[i])
        if(!done[to[i]])
            dfss(to[i],0,to[i],len[i]);
    fo(i,1,dis[0])v[i]=i;
    sort(v+1,v+dis[0]+1,cmp);
    int j=dis[0],k=dis[0];
    fo(i,1,dis[0]){
        for(;(i<=j)&&(dis[v[i]]+dis[v[j]]>e);j--);
        k=min(k,j);int kk=k,ok=0;
        for(;(i<=k)&&(dis[v[i]]+dis[v[k-1]]>=s);k--)
            if((tag[v[i]]!=tag[v[k-1]])&&(dis[v[i]]+dis[v[k-1]]>=s)&&(dis[v[i]]+dis[v[k-1]]<=e)){
                ans=min(ans,dis[v[k-1]]+dis[v[i]]);
            }
        kk+=dis[v[i]]+dis[v[k]]<s;
        if(!ok)
            fo(l,kk,j)
                if((tag[v[i]]!=tag[v[l]])&&(dis[v[l]]+dis[v[i]]>=s)&&(dis[v[l]]+dis[v[i]]<=e)){
                    ans=min(ans,dis[v[l]]+dis[v[i]]);
                    break;
                }
        if(dis[v[i]]+dis[v[j]]>e)break;
    }
    for(int i=begin[now];i;i=next[i])
        if(!done[to[i]])
            dfs(root(to[i]));
}
int main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    scanf("%d%d%d",&n,&s,&e);
    fo(i,1,n-1){
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        insert(u,v,w);insert(v,u,w);
    }
    dfs(root(1));
    if(ans!=inf)printf("%d",ans);
    else printf("-1");
    return 0;
}
内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值