BZOJ 1758 【WC2010】 重建计划
题目链接:重建计划
这道题现在已经成为一道板子题了……
这是个非常显然的0-1分数规划,可以二分答案之后树分治判定一下。注意树分治的时候如果使用单调队列,需要把所有儿子预先按最大深度排好序,否则会被扫把型的数据卡到\(n^2\log n\)。
然后跑得非常慢……于是把二分答案改成了Dinkelbach迭代法。Dinkelbach迭代法就是每次用当前最优解来更新答案的界,跑得比香港记者还快
听说这玩意儿复杂度上界是\(\log\)级别的?然而我并不会证……感觉这玩意儿就是玄学啊……
二分答案代码:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- #include<vector>
- #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
- #define maxn 100010
- #define INF 2147483647
- #define eps 1e-6
- using 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]]<dep[to[y]];}
- void link(int x,int y,int z){
- to[++tt]=y;next[tt]=head[x];
- head[x]=tt; c[tt]=z;
- }
- void dfs(int u,int x){
- siz[u]=1; dx[u]=0; dep[u]=x;
- d[++ld]=u; vis[u]=1;
- for(int i=head[u],v;v=to[i],i;i=next[i])
- if(!vis[v]){
- dfs(v,x+1); siz[u]+=siz[v];
- dx[u]=max(dx[u],siz[v]);
- dep[u]=max(dep[u],dep[v]);
- }
- vis[u]=0;
- }
- void getroot(int u,int fa){
- ld=0; dfs(u,0); int k=0,_k=INF;
- for(int l=1,i;i=d[l],l<=ld;l++){
- dx[i]=max(dx[i],siz[u]-siz[i]);
- if(dx[i]<_k) k=i,_k=dx[i];
- }
- vis[k]=1; fr[fa]=k;
- for(int i=head[k];i;i=next[i])
- if(!vis[to[i]]) getroot(to[i],i);
- ld=0; dfs(k,0); vis[k]=0; la=0;
- for(int i=head[k];i;i=next[i]) a[++la]=i;
- sort(a+1,a+la+1,cmp); next[a[la]]=0; head[k]=a[1];
- for(int i=1;i<la;i++) next[a[i]]=a[i+1];
- }
- void getdis(int u,int de){
- vis[u]=1; lc=max(lc,de); c2[de]=max(c2[de],dis[u]);
- for(int i=head[u],v;v=to[i],i;i=next[i])
- if(!vis[v]) dis[v]=dis[u]+c[i],getdis(v,de+1);
- vis[u]=0;
- }
- void work(int u,int fa){
- int k=fr[fa]; vis[k]=1; int cl=0;
- for(int i=head[k],v,l,r,no;v=to[i],i;i=next[i]){
- if(vis[v]) continue; lc=0;
- dis[v]=c[i]; getdis(v,1); l=r=0; no=0;
- for(int j=lc;j;j--){
- while(no<=R-j && no<=cl){
- while(l<r && c1[s[r-1]]<=c1[no]) r--;
- s[r++]=no++;
- }
- while(l<r && s[l]<L-j) l++;
- if(l<r) ans=max(ans,c2[j]+c1[s[l]]);
- if(ans+eps>=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<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- #include<vector>
- #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
- #define maxn 100010
- #define INF 2147483647
- using 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]]<dep[to[y]];}
- void link(int x,int y,int z){
- to[++tt]=y;next[tt]=head[x];
- head[x]=tt; c[tt]=z;
- }
- void dfs(int u,int x){
- siz[u]=1; dx[u]=0; dep[u]=x;
- d[++ld]=u; vis[u]=1;
- for(int i=head[u],v;v=to[i],i;i=next[i])
- if(!vis[v]){
- dfs(v,x+1); siz[u]+=siz[v];
- dx[u]=max(dx[u],siz[v]);
- dep[u]=max(dep[u],dep[v]);
- }
- vis[u]=0;
- }
- void getroot(int u,int fa){
- ld=0; dfs(u,0); int k=0,_k=INF;
- for(int l=1,i;i=d[l],l<=ld;l++){
- dx[i]=max(dx[i],siz[u]-siz[i]);
- if(dx[i]<_k) k=i,_k=dx[i];
- }
- vis[k]=1; fr[fa]=k;
- for(int i=head[k];i;i=next[i])
- if(!vis[to[i]]) getroot(to[i],i);
- ld=0; dfs(k,0); vis[k]=0; la=0;
- for(int i=head[k];i;i=next[i]) a[++la]=i;
- sort(a+1,a+la+1,cmp); next[a[la]]=0; head[k]=a[1];
- for(int i=1;i<la;i++) next[a[i]]=a[i+1];
- }
- void getdis(int u,int de){
- vis[u]=1; lc=max(lc,de); c2[de]=max(c2[de],dis[u]);
- for(int i=head[u],v;v=to[i],i;i=next[i])
- if(!vis[v]) dis[v]=dis[u]+c[i],getdis(v,de+1);
- vis[u]=0;
- }
- void work(int u,int fa){
- int k=fr[fa]; vis[k]=1; int cl=0; double x;
- for(int i=head[k],v,l,r,no;v=to[i],i;i=next[i]){
- if(vis[v]) continue; lc=0;
- dis[v]=c[i]; getdis(v,1); l=r=0; no=0;
- for(int j=lc;j;j--){
- while(no<=R-j && no<=cl){
- while(l<r && c1[s[r-1]]<=c1[no]) r--;
- s[r++]=no++;
- }
- while(l<r && s[l]<L-j) l++;
- if(l<r){
- x=(c2[j]+c1[s[l]])/(j+s[l]);
- if(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+
BZOJ 1758 【WC2010】 重建计划的更多相关文章
- bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check
[Wc2010]重建计划 Time Limit: 40 Sec Memory Limit: 162 MBSubmit: 4345 Solved: 1054[Submit][Status][Disc ...
- bzoj 1758: [Wc2010]重建计划
Description Input 第 一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案 ...
- BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...
- BZOJ 1758: [Wc2010]重建计划 [暂时放弃]
今天晚上思维比较乱,以后再写写吧#include <iostream> #include <cstdio> #include <cstring> #include ...
- BZOJ 1758: [Wc2010]重建计划 01分数规划+点分治+单调队列
code: #include <bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in", ...
- BZOJ1758: [Wc2010]重建计划
题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...
- 洛谷 P4292 [WC2010]重建计划 解题报告
P4292 [WC2010]重建计划 题目描述 \(X\)国遭受了地震的重创, 导致全国的交通近乎瘫痪,重建家园的计划迫在眉睫.\(X\)国由\(N\)个城市组成, 重建小组提出,仅需建立\(N-1\ ...
- [WC2010]重建计划 长链剖分
[WC2010]重建计划 LG传送门 又一道长链剖分好题. 这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分. 如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结. 首先一看求平均值最大 ...
- BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)
题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...
- 【bzoj1758】[Wc2010]重建计划
Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...
随机推荐
- [LeetCode] 549. Binary Tree Longest Consecutive Sequence II_ Medium tag: DFS recursive
Given a binary tree, you need to find the length of Longest Consecutive Path in Binary Tree. Especia ...
- leetcode & lintcode 题解
刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...
- MatLab 2014a编译jar包时mcc无法使用的问题
http://blog.csdn.net/heroafei/article/details/43273373 MatLab 2014a编译jar包时mcc无法使用的问题 2015-01-29 16:5 ...
- JaveScript-简介
1.JaveScript:脚本语言.(弱类型语言)可以写在head,也可以写在head里,同样可以写在html外面<script src=""></script& ...
- sql server 获取分隔字符串后的长度
--方法1 --sql 分隔字符串,返回个数 CREATE function f_splitLen_1 ( @str varchar(1024), --要分割的字符串 @split varc ...
- GCC编译器ABI
ABI与EABI 1)ABI(Application Binary Interface for the ARM Architecture),描述了应用程序与cpu内核的低级接口. ABI允许编译好的目 ...
- How To View the HTML Source in Google Chrome
Whether you are new to the web industry or a seasoned veteran, viewing the HTML source of different ...
- jq 自定义标注小组件 $.widget
html 部分 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- org.apache.catalina.core.StandardWrapperValve invoke的解决办法
org.apache.catalina.core.StandardWrapperValve invoke的解决办法 比较容易错的地方是页面带参数进行跳转,由于跳转之后的页面本身也要执行一部分sql语句 ...
- ES6学习笔记之map、set与数组、对象的对比
ES6 ES5中的数据结构,主要是用Array和Object.在ES6中主要新增了Set和Map数据结构.到目前为止,常用的数据结构有四种Array.Object.Set.Map.下面话不多说了,来一 ...