博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 1758 【WC2010】 重建计划
阅读量:5208 次
发布时间:2019-06-14

本文共 3252 字,大约阅读时间需要 10 分钟。

题目链接:

  这道题现在已经成为一道板子题了……

  这是个非常显然的0-1分数规划,可以二分答案之后树分治判定一下。注意树分治的时候如果使用单调队列,需要把所有儿子预先按最大深度排好序,否则会被扫把型的数据卡到\(n^2\log n\)。

  然后跑得非常慢……于是把二分答案改成了Dinkelbach迭代法。Dinkelbach迭代法就是每次用当前最优解来更新答案的界,跑得比香港记者还快

  听说这玩意儿复杂度上界是\(\log\)级别的?然而我并不会证……感觉这玩意儿就是玄学啊……

  二分答案代码:

#include
#include
#include
#include
#include
#include
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)#define maxn 100010#define INF 2147483647#define eps 1e-6using namespace std;typedef long long llg;int n,L,R,siz[maxn],dx[maxn],lc,dep[maxn];int fr[maxn<<1],a[maxn],la,d[maxn],ld,s[maxn];int head[maxn],next[maxn<<1],to[maxn<<1],tt;double c[maxn<<1],lt,dis[maxn];double c1[maxn],c2[maxn],ans;bool vis[maxn];int getint(){ int w=0;bool q=0; char c=getchar(); while((c>'9'||c<'0')&&c!='-') c=getchar(); if(c=='-') c=getchar(),q=1; while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;}bool cmp(int x,int y){return dep[to[x]]
=0) break; } cl=max(cl,lc); for(int j=1;j<=lc;j++) c1[j]=max(c1[j],c2[j]),c2[j]=-1e9; } for(int i=1;i<=cl;i++) c1[i]=-1e9; if(ans+eps>=0){vis[k]=0;return;} for(int i=head[k];i;i=next[i]) if(!vis[to[i]]) work(to[i],i); vis[k]=0;}bool check(double x){ for(int i=1;i<=tt;i++) c[i]+=lt-x; lt=x; ans=-1e9; work(1,0); return ans+eps>=0;}int main(){ File("a"); n=getint(),L=getint(),R=getint(); for(int i=2,u,v;i<=n;i++){ u=getint(),v=getint(); to[++tt]=v;next[tt]=head[u];head[u]=tt; to[++tt]=u;next[tt]=head[v];head[v]=tt; c[tt-1]=c[tt]=getint(); } getroot(1,0); for(int i=1;i<=n;i++) c1[i]=c2[i]=-1e9; double l=0,r=1000000,mid; while(r-l>=1e-4){ mid=(l+r)*0.5; if(check(mid)) l=mid; else r=mid; } printf("%.3lf",l); return 0;}

   Dinkelbach迭代法代码:

#include
#include
#include
#include
#include
#include
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)#define maxn 100010#define INF 2147483647using namespace std;typedef long long llg;int n,L,R,siz[maxn],dx[maxn],lc,dep[maxn];int fr[maxn<<1],a[maxn],la,d[maxn],ld,s[maxn];int head[maxn],next[maxn<<1],to[maxn<<1],tt;double c[maxn<<1],lt,dis[maxn];double c1[maxn],c2[maxn],ans;bool vis[maxn];int getint(){ int w=0;bool q=0; char c=getchar(); while((c>'9'||c<'0')&&c!='-') c=getchar(); if(c=='-') c=getchar(),q=1; while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;}bool cmp(int x,int y){return dep[to[x]]
ans) ans=x; } } cl=max(cl,lc); for(int j=1;j<=lc;j++) c1[j]=max(c1[j],c2[j]),c2[j]=-1e9; } for(int i=1;i<=cl;i++) c1[i]=-1e9; for(int i=head[k];i;i=next[i]) if(!vis[to[i]]) work(to[i],i); vis[k]=0;}void check(double x){ for(int i=1;i<=tt;i++) c[i]+=lt-x; lt=x; ans=-1e9; work(1,0);}int main(){ File("a"); n=getint(),L=getint(),R=getint(); for(int i=2,u,v;i<=n;i++){ u=getint(),v=getint(); to[++tt]=v;next[tt]=head[u];head[u]=tt; to[++tt]=u;next[tt]=head[v];head[v]=tt; c[tt-1]=c[tt]=getint(); } getroot(1,0); for(int i=1;i<=n;i++) c1[i]=c2[i]=-1e9; double now=0; check(0); while(ans>1e-4) now+=ans,check(now); printf("%.3lf",now); return 0;}

   实测BZOJ上前一份代码24s+,后一份代码只要5s+

转载于:https://www.cnblogs.com/lcf-2000/p/6612171.html

你可能感兴趣的文章
【转】我们为什么要使用AOP?
查看>>
center os7 安装mysql
查看>>
static修饰符与递归函数
查看>>
java修炼之道(转)
查看>>
ProgressBar样式(转)
查看>>
python学习笔记:try与except处理异常语句
查看>>
windows7中的“mklink命令”
查看>>
sklearn中的损失函数
查看>>
Java线程同步操作
查看>>
Oracle控制文件操作
查看>>
“轻笔记”使用心得
查看>>
融通人工智能指数(LOF)净值下跌1.08% 请保持关注
查看>>
jenkins(四):Jenkins一个最简单的freestyle项目
查看>>
关于安装虚拟机
查看>>
js全局变量优点和缺点
查看>>
GRPC 截止时间与元数据
查看>>
Java--java.lang.Object
查看>>
Bootstrap使用详解
查看>>
Delphi CreateMutex 防止程序多次运行
查看>>
python016 Python3 数据结构
查看>>