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

来源:互联网 发布:淘宝两个店铺绑定 编辑:程序博客网 时间:2024/04/28 12:57

题目大意

给出一棵树,求出最小的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;}
0 0