【JZOJ4715】树上路径

来源:互联网 发布:h5 全景相片源码 编辑:程序博客网 时间:2024/03/28 17:01

Description

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

题目描述使人神清气爽。——LYD729

Solution

树上多条路径问题显然用点分治解决。

于是像常规点分治那样,求出每个点到重心的距离,排序。然后枚举开头,二分出一个位置使得距离大于等于下界,然后如果这两个点在同一棵子树就把二分出的点跳到另一棵子树上。

Code

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 100001#define M 200001using namespace std;int p,q;int to[M],next[M],last[M],num=0;int val[M];int siz[N];int dis[N];int fa[N];int f[N];bool vis[N];struct node{    int x,f;}d[N];int tot;void link(int x,int y,int c){    num++;    to[num]=y;    next[num]=last[x];    last[x]=num;    val[num]=c;}bool cmp(node x,node y){    return x.x<y.x;}int rt;int cnt=0;void get(int x,int t,int from){    for(int i=last[x];i;i=next[i])    {        int v=to[i];        if(v!=t && !vis[v])        {            dis[v]=dis[x]+val[i];            get(v,x,from);        }    }    if(dis[x])    {        tot++;        d[tot].x=dis[x];        d[tot].f=from;    }}void find(int x,int p,int t){    siz[x]=1;    f[x]=0;    for(int i=last[x];i;i=next[i])    {        int v=to[i];        if(v!=t && !vis[v])        {            find(v,p,x);            siz[x]+=siz[v];            f[x]=max(f[x],siz[v]);        }    }    f[x]=max(f[x],p-siz[x]);    if(f[x]<f[rt]) rt=x;}int ans=2147483647;int nx[N];void calc(){    sort(d+1,d+tot+1,cmp);    nx[tot]=tot+1;    fd(i,tot-1,1)    if(d[i].f==d[i+1].f) nx[i]=nx[i+1];    else nx[i]=i+1;    if(tot==1 && d[1].x>=p && d[1].x<=q && d[1].x<ans) ans=d[1].x;     fo(i,1,tot-1)    {        if(d[i].x>=p && d[i].x<ans) ans=d[i].x;        int l=i+1,r=tot;        while(l+1<r)        {            int mid=(l+r)/2;            if(d[i].x+d[mid].x>=p) r=mid;            else l=mid;        }        int t=l;        if(d[i].x+d[t].x<p) t++;        while(d[i].f==d[t].f) t=nx[t];        if(t>tot) continue;        if(d[i].x+d[t].x>=p && d[i].x+d[t].x<=q)        {            if(ans>d[i].x+d[t].x) ans=d[i].x+d[t].x;        }    }}void dfs(int x,int t){    vis[x]=true;    tot=0;    dis[x]=0;    for(int i=last[x];i;i=next[i])    {        int v=to[i];        if(v!=t && !vis[v])        {            dis[v]=val[i];            get(v,x,v);        }    }    calc();    for(int i=last[x];i;i=next[i])    {        int v=to[i];        if(!vis[v] && v!=t)        {            rt=0;            find(v,siz[v],x);            dfs(rt,x);        }    }}int main(){    int n;    cin>>n>>p>>q;    fo(i,1,n-1)    {        int x,y,c;        scanf("%d %d %d",&x,&y,&c);        link(x,y,c);        link(y,x,c);    }    rt=0;    f[0]=2147483647;    find(1,n,0);    dfs(rt,0);    if(ans>q) cout<<-1;    else cout<<ans;}
2 0
原创粉丝点击