树上路径

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

数据范围:\(n\le1e5,S\le E\le 1e9\)

Solution:

这里提供两种思路,第一种是二分k,点分治求出距离,时间复杂度\(O(n\,log\,n\,log\,(E-S))\),比较容易写挂,且容易TLE

第二种是对于每一个点,预处理出离他最近的不同子树的且满足距离之和大于S的点,然后即可暴力更新答案

这里给出第二种写法的代码(第一种写T了QAQ)

Code:

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define inf 2147483647
using namespace std;
const int N=2e6+5;
int rt,cnt,szt,head[N],sz[N],mx[N],go[N];
int n,L,R,tot,dis[N],vis[N],ans=inf;
struct Edge{int nxt,to,val;}edge[N<<1];
struct pos{int dis,be;}p[N];
inline bool cmp(pos a,pos b){return a.dis<b.dis;}
void ins(int x,int y,int z){
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;edge[cnt].val=z;
    head[x]=cnt;
}
void getrt(int x,int fa){
    mx[x]=0,sz[x]=1;
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to;
        if(vis[y]||y==fa) continue;
        getrt(y,x);sz[x]+=sz[y];
        mx[x]=max(mx[x],sz[y]);
    }
    mx[x]=max(mx[x],szt-sz[x]);
    if(mx[x]<mx[rt]) rt=x;
}
void getdis(int x,int fa,int d,int rtt){
    p[++tot].dis=d;p[tot].be=rtt;
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to;
        if(vis[y]||y==fa) continue;
        getdis(y,x,d+edge[i].val,rtt);
    }
}
int find(int l,int r,int x){
    while(l<r){
        int mid=(l+r)>>1;
        if(x+p[mid].dis<L) l=mid+1;
        else r=mid;
    }return l;
}
void divide(int x){
    vis[x]=1;tot=0;
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to;
        if(vis[y]) continue;
        getdis(y,x,edge[i].val,y);
    }
    sort(p+1,p+tot+1,cmp);
    for(int i=1;i<=tot;i++)
        if(p[i].dis>=L&&p[i].dis<=R) ans=min(ans,p[i].dis);
    for(int i=tot;i>=1;i--){
        if(p[i].be!=p[i+1].be) go[i]=i+1;
        else go[i]=go[i+1];
    }p[tot+1].dis=0;
    for(int i=1;i<=tot;i++){
        int u=find(i+1,tot,p[i].dis);
        if(p[u].be==p[i].be) u=go[u];
        int now=p[u].dis+p[i].dis;
        if(now>=L&&now<=R) ans=min(ans,now);
        go[i]=0;
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int y=edge[i].to;
        if(vis[y]) continue;
        szt=sz[y];rt=0;getrt(y,x);
        divide(rt);
    }
}
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    n=read(),L=read(),R=read();
    if(R<L) swap(L,R);
    for(int i=1;i<n;i++){
        int x=read(),y=read(),z=read();
        ins(x,y,z);ins(y,x,z);
    }
    mx[rt]=inf;szt=n;getrt(1,0);
    divide(rt);printf("%d\n",ans==inf?-1:ans);
    return 0;
}
posted @ 2019-05-06 21:00  DQY_dqy  阅读(188)  评论(0编辑  收藏  举报