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