首页 技术 正文
技术 2022年11月6日
0 收藏 562 点赞 602 浏览 2680 个字

题目大意:给定一棵树,求一条长度在L到R的一条路径,使得边权的平均值最大。

题解

树上路径最优化问题,不难想到点分治。

如果没有长度限制,我们可以套上01分数规划的模型,让所有边权减去mid,求一条路径长度非负。

现在考虑有L和R的限制,就是我们在拼接两条路径的时候,每条路径能够匹配的是按深度排序后一段连续区间,我们只需要维护区间最大值。

然后随着深度的单调变化,这个区间在滑动,这就变成了滑动窗口问题。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 100002
#define inf 2e9
#define Re register
using namespace std;
typedef long long ll;
const double eps=1e-;
double mid,ans,ma,deep[N],man[N];
int tot,head[N],dp[N],q[N],minl,maxl,size[N],maxdeep,root,sum,n,dep[N],que[N],L,R;
bool vis[N],visit[N];
inline ll rd(){
ll x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{int n,to,l;}e[N<<];
inline void add(int u,int v,int l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;}
void getsize(int u,int fa){
size[u]=;
for(Re int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!vis[e[i].to]){
int v=e[i].to;
getsize(v,u);size[u]+=size[v];
}
}
inline int mx(int a,int b){return a>b?a:b;}
inline double maxx(double a,double b){return a>b?a:b;}
void getroot(int u,int fa){
dp[u]=;size[u]=;
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;
getroot(v,u);size[u]+=size[v];
dp[u]=mx(dp[u],size[v]);
}
dp[u]=mx(dp[u],sum-size[u]);
if(dp[u]<dp[root])root=u;
}
void getdeep(int u,int fa){
maxdeep=mx(maxdeep,dep[u]);
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;deep[v]=deep[u]+e[i].l-mid;dep[v]=dep[u]+;
getdeep(v,u);
}
}
void getcalc(int u,int fa){
man[dep[u]]=maxx(man[dep[u]],deep[u]);
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;getcalc(v,u);
}
}
inline bool getcheck(int u){
maxdeep=;bool tag=;
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;deep[v]=e[i].l-mid;dep[v]=;
getdeep(v,u);
int h=,t=;que[h]=v;visit[v]=;
while(h<=t){
int x=que[h++];
for(int j=head[x];j;j=e[j].n){
int v=e[j].to;
if(!vis[v]&&!visit[v]&&v!=u)que[++t]=v,visit[v]=;
}
}
int p=;L=;R=;q[++R]=;
for(Re int i=t;i>=;--i){
int x=que[i];visit[x]=;
while(p+dep[x]<maxl&&p<maxdeep){
int x=++p;
while(L<=R&&man[x]>=man[q[R]])R--;
q[++R]=x;
}
while(L<=R&&q[L]+dep[x]<minl)L++;
if(L<=R&&deep[x]+man[q[L]]>=)tag=;
}
getcalc(v,u);
}
for(Re int i=;i<=maxdeep;++i)man[i]=-inf;
return tag;
}
inline void getans(int u){
double l=ans,r=ma;
while(r-l>eps){
mid=(l+r)/2.0;
if(getcheck(u)){ans=mid;l=mid;}else r=mid;
}
}
void solve(int u){
getans(u);vis[u]=;
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
root=n+;sum=size[v];
getroot(v,u);//getsize(root,0);
solve(root);
}
}
int main(){
n=rd();minl=rd();maxl=rd();int u,v,w;
for(int i=;i<=n;++i)man[i]=-inf;
ma=-1e9;ans=1e9;
for(Re int i=;i<n;++i){
u=rd();v=rd();w=rd();ma=maxx(ma,(double)w);ans=min(ans,(double)w);
add(u,v,w);add(v,u,w);
}
dp[root=n+]=n;sum=n;
getroot(,);//getsize(root,0);
solve(root);
printf("%.3lf",ans);
return ;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,080
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,554
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,403
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,178
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,815
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898