【NOIP提高】树上路径

来源:互联网 发布:下载美颜视频软件 编辑:程序博客网 时间:2024/04/26 18:15

Description

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

Solution

这个一眼的树分治啊!
但是标了NOIP的题不敢打树分治,结果TAT。
其实打了个不确定的方法,但是在不是菊花图的情况下跑的很快。
每次对每个点每个儿子的子树与这个点的距离放进一个数组里,然后数组两两合并,并同时求答案。
比如把一个儿子节点的所有值放进了数组a,然后要合并到数组b里面。
a,b数组先排一个序。
顺序用i枚举b数组,然后找到第一个a里面的j,满足b[i]+a[j]>=s,然后更新答案。
之后a数组里面所有≤e的数都放进b数组里面,可以用归并,但是直接排序不会爆。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define rep(i,a) for(i=first[a];i;i=next[i])const int maxn=100007;using namespace std;int i,j,k,t,n,m,ans;int first[maxn*2],next[maxn*2],last[maxn*2],num,size[maxn],chang[maxn*2],er;int z,f[maxn],g[maxn],l,r,mid,yi,deep[maxn],s,e;bool az[maxn];void add(int x,int y,int z){    last[++num]=y;next[num]=first[x];first[x]=num;chang[num]=z;}void zhao(int x,int y){    int i;size[x]=1;    rep(i,x){        if(last[i]!=y&&!az[last[i]]){            zhao(last[i],x);            size[x]+=size[last[i]];        }    }}void zhaozhong(int x,int y){   int i;bool dz=1;   rep(i,x){       if(last[i]!=y&&!az[last[i]]){           zhaozhong(last[i],x);           if(size[last[i]]>yi/2)dz=0;       }   }   if(yi-size[x]<=yi/2&&dz)z=x;}void zhaoshen(int x,int y,int z){    g[++g[0]]=x;    int i;    deep[x]=deep[y]+chang[z];    rep(i,x){        if(last[i]!=y&&!az[last[i]]){            zhaoshen(last[i],x,i);        }    }}bool cmp(int x,int y){return deep[x]<deep[y];}void calc(int *x){    int k=0,j=f[0],i,l;    sort(x+1,x+x[0]+1,cmp);    sort(f+1,f+f[0]+1,cmp);    int o=x[0];    fo(i,1,j){        while(o&&deep[f[i]]+deep[x[o]]>=s)o--;        if(o==x[0])continue;        o++;      //  if(!o)break;        if(deep[f[i]]+deep[x[o]]<=e&&deep[f[i]]+deep[x[o]]>=s)        ans=min(ans,deep[f[i]]+deep[x[o]]);        if(ans==350222){            ans=ans;        }    }    o=x[0];    fo(i,1,o){        if(deep[x[i]]>e)break;        f[++f[0]]=x[i];    }}void fenzhi(int x){    int i,u;    zhao(x,0);yi=size[x];    zhaozhong(x,0);deep[z]=0;f[f[0]=1]=z;az[z]=1;er=0;    u=z;    rep(i,z){        if(!az[last[i]]){            g[0]=0;            zhaoshen(last[i],z,i);            calc(g);        }    }    rep(i,z){        if(!az[last[i]]){            fenzhi(last[i]);        }    }}int main(){//  freopen("fan.in","r",stdin);    scanf("%d%d%d",&n,&s,&e);    fo(i,1,n-1){        scanf("%d%d%d",&k,&l,&t);        add(k,l,t);add(l,k,t);    }    ans=0x7fffffff;    fenzhi(1);    if(ans==0x7fffffff)printf("-1\n");    else printf("%d\n",ans);}
1 0
原创粉丝点击