热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[WC2010]重建方案:分数规划、点分治与单调队列的应用分析

题目旨在解决树上的路径最优化问题,具体为在给定的树中寻找一条长度介于L到R之间的路径,使该路径上的边权平均值最大化。通过点分治策略,可以有效地处理此类问题。若无长度限制,可采用01分数规划模型,将所有边权减去一个常数m,从而简化计算过程。此外,利用单调队列优化动态规划过程,进一步提高算法效率。

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

题解

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

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

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

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

代码

#include
#include

#include

#include

#define N 100002
#define inf 2e9
#define Re register
using namespace std;
typedef
long long ll;
const double eps=1e-4;
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
=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c==-)f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct edge{int n,to,l;}e[N<<1];
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]
=1;
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]
=0;size[u]=1;
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]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]+1;
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
=0;bool tag=0;
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]=1;
getdeep(v,u);
int h=1,t=1;que[h]=v;visit[v]=1;
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]=1;
}
}
int p=0;L=1;R=0;q[++R]=0;
for(Re int i=t;i>=1;--i){
int x=que[i];visit[x]=0;
while(p+dep[x]maxdeep){
int x=++p;
while(L<=R&&man[x]>=man[q[R]])R--;
q[
++R]=x;
}
while(L<=R&&q[L]+dep[x];
if(L<=R&&deep[x]+man[q[L]]>=0)tag=1;
}
getcalc(v,u);
}
for(Re int i=1;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]
=1;
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
root
=n+1;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=1;i<=n;++i)man[i]=-inf;
ma
=-1e9;ans=1e9;
for(Re int i=1;ii){
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+1]=n;sum=n;
getroot(
1,0);//getsize(root,0);
solve(root);
printf(
"%.3lf",ans);
return 0;
}

 


推荐阅读
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文介绍如何使用 NSTimer 实现倒计时功能,详细讲解了初始化方法、参数配置以及具体实现步骤。通过示例代码展示如何创建和管理定时器,确保在指定时间间隔内执行特定任务。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文介绍如何在 Xcode 中使用快捷键和菜单命令对多行代码进行缩进,包括右缩进和左缩进的具体操作方法。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
author-avatar
傻瓜等傻子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有