bzoj
luogu
loj上可以交部分分程序

description

小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面。田野上有 \(n\) 棵许愿树,编号 \(1,2,3, \ldots ,n\),每棵树可以看作平面上的一个点,其中第 \(i\) 棵树 (\(1 \leq i \leq n\)) 位于坐标 \((x_i,y_i)\)。任意两棵树的坐标均不相同。

老司机 Mr. P 从原点 \((0,0)\) 驾车出发,进行若干轮行动。每一轮,Mr. P 首先选择任意一个满足以下条件的方向:

  1. 为左、右、上、左上 \(45^{\circ}\) 、右上 \(45^{\circ}\) 五个方向之一。
  2. 沿此方向前进可以到达一棵他尚未许愿过的树。

完成选择后,Mr. P 沿该方向直线前进,必须到达该方向上距离最近的尚未许愿的树,在树下许愿并继续下一轮行动。如果没有满足条件的方向可供选择,则停止行动。他会采取最优策略,在尽可能多的树下许愿。若最优策略不唯一,可以选择任意一种。

不幸的是,小园丁 Mr. S 发现由于田野土质松软,老司机 Mr. P 的小汽车在每轮行进过程中,都会在田野上留下一条车辙印,一条车辙印可看作以两棵树(或原点和一棵树)为端点的一条线段。

在 Mr. P 之后,还有很多许愿者计划驾车来田野许愿,这些许愿者都会像 Mr. P 一样任选一种最优策略行动。Mr. S 认为非左右方向(即上、左上\(45^{\circ}\) 、右上 \(45^{\circ}\) 三个方向)的车辙印很不美观,为了维护田野的形象,他打算租用一些轧路机,在这群许愿者到来之前夯实所有「可能留下非左右方向车辙印」的地面。

「可能留下非左右方向车辙印」的地面应当是田野上的若干条线段,其中每条线段都包含在某一种最优策略的行进路线中。每台轧路机都采取满足以下三个条件的工作模式:

  1. 从原点或任意一棵树出发。
  2. 只能向上、左上 \(45^{\circ}\) 、右上 \(45^{\circ}\) 三个方向之一移动,并且只能在树下改变方向或停止。
  3. 只能经过「可能留下非左右方向车辙印」的地面,但是同一块地面可以被多台轧路机经过。

现在 Mr. P 和 Mr. S 分别向你提出了一个问题:

  1. 请给 Mr .P 指出任意一条最优路线。
  2. 请告诉 Mr. S 最少需要租用多少台轧路机。

sol

这道题又是个二合一啊。
对于第一问,为老司机求出一条最优路径,这个我们可以\(dp\)得到。
因为行走路线不能向下,我们令\(y_i\)相同的树为同一层,可以发现最优决策一定是:先在同一层中把所有可以走到的树全部走到,再向上走到达下一层。这么一来每一层就会有一个确定的入点和出点。(这里注意一下并不是所有层都会被经过)
先求出每个点向下、左下、右下三个方向到达的最近的树,这是这个点作为这一层的进入点的三个前驱。设\(f_i\)表示到达第\(i\)棵树作为当前这一层的出点时最多经过多少棵树,那么就可以枚举入点,分三种情况讨论:
1、入点就是出点,那么这一层就只能经过这一棵树。
2、入点在出点的左侧,那么可以经过出点左侧的所有树(在这一层中先一直往左走再一直往右走直到到达出点)
3、入点在出点的右侧,那么可以经过出点右侧的所有树。
然后这个\(dp\)是可以做到\(O(n)\)的。输出方案的时候,其实可以不记录\(dp\)转移的前驱,只要照着转移的方式再扫一遍所有前驱,看看是从哪个位置转移来的即可。

接下来就需要处理小园丁的问题。我们先可以求出那些边是必须经过的边,然后问题就转化为了要求这些边的流量都至少是\(1\)。
这是一个上下界网络流的问题。我们先假设这些边的流量是\(1\),这样有的点就会不满足流量守恒。新建源点汇点对这些流量不平衡的点进行补流或者是分流。
因为求的是最小流,按照最小流的一般思路是先从新建源点向新建汇点跑最大流,在不建立从原汇点到原源点的\(inf\)的情况下,这样跑出的最大流就是原图中最多的可以承担的流量,所以答案就是\(\sum_{d_i>0}d_i\)-最大流。

code

码农题啊qwq

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
using namespace std;
int gi(){int x=0,w=1;char ch=getchar();while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();if (ch=='-') w=0,ch=getchar();while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return w?x:-x;
}
#define cmax(a,b) (a<b?a=b:a)
const int N = 5e4+5;
const int inf = 1e9;
struct node{int x,y,id;bool operator < (const node &b) const{if (y==b.y) return x<b.x;return y<b.y;}
}p[N];
int n,o[N],len,d[N],ld[N],rd[N],f[N],g[N],tag[N],ans;
vector<int>v[N];map<int,int>M;queue<int>Q;
struct network{struct edge{int to,nxt,w;}a[N*100];int S,T,head[N],cnt,tot,du[N],dep[N],cur[N];void link(int u,int v){for (int e=head[u];e;e=a[e].nxt) if (a[e].to==v) return;a[++cnt]=(edge){v,head[u],inf};head[u]=cnt;a[++cnt]=(edge){u,head[v],0};head[v]=cnt;++du[v];--du[u];tag[u]=1;}void link(int u,int v,int w){a[++cnt]=(edge){v,head[u],w};head[u]=cnt;a[++cnt]=(edge){u,head[v],0};head[v]=cnt;}bool bfs(){memset(dep,0,sizeof(dep));dep[S]=1;Q.push(S);while (!Q.empty()){int u=Q.front();Q.pop();for (int e=head[u];e;e=a[e].nxt)if (a[e].w&&!dep[a[e].to])dep[a[e].to]=dep[u]+1,Q.push(a[e].to);}return dep[T];}int dfs(int u,int f){if (u==T) return f;for (int &e=cur[u];e;e=a[e].nxt)if (a[e].w&&dep[a[e].to]==dep[u]+1){int tmp=dfs(a[e].to,min(a[e].w,f));if (tmp) {a[e].w-=tmp;a[e^1].w+=tmp;return tmp;}}return 0;}int dinic(){int res=0;while (bfs()){for (int i=0;i<=T;++i) cur[i]=head[i];while (int tmp=dfs(S,inf)) res+=tmp;}return res;}int work(){S=n+1;T=n+2;for (int i=0;i<=n;++i){if (du[i]>0) link(S,i,du[i]),tot+=du[i];if (du[i]<0) link(i,T,-du[i]);}return tot-dinic();}
}G;
bool cmp(node i,node j){return i.id<j.id;}
int pre(int x){if (~d[x]&&g[x]==f[d[x]]) return d[x];if (~ld[x]&&g[x]==f[ld[x]]) return ld[x];if (~rd[x]&&g[x]==f[rd[x]]) return rd[x];
}
void dfs(int u){if (!u) return;int sz=v[p[u].y].size(),pos=0;while (v[p[u].y][pos]!=u) ++pos;if (f[u]==g[u]+1) {dfs(pre(u));printf("%d ",u);return;}for (int i=0;i<pos;++i){int x=v[p[u].y][i];if (f[u]==g[x]+pos+1){dfs(pre(x));for (int j=i;~j;--j) printf("%d ",v[p[u].y][j]);for (int j=i+1;j<=pos;++j) printf("%d ",v[p[u].y][j]);return;}}for (int i=pos+1;i<sz;++i){int x=v[p[u].y][i];if (f[u]==g[x]+sz-pos){dfs(pre(x));for (int j=i;j<sz;++j) printf("%d ",v[p[u].y][j]);for (int j=i-1;j>=pos;--j) printf("%d ",v[p[u].y][j]);return;}}
}
void build(int u){int sz=v[p[u].y].size(),pos=0;while (v[p[u].y][pos]!=u) ++pos;if (f[u]==g[u]+1){if (~d[u]&&g[u]==f[d[u]]) G.link(d[u],u);if (~ld[u]&&g[u]==f[ld[u]]) G.link(ld[u],u);if (~rd[u]&&g[u]==f[rd[u]]) G.link(rd[u],u);}for (int i=0;i<pos;++i){int x=v[p[u].y][i];if (f[u]==g[x]+pos+1){if (~d[x]&&g[x]==f[d[x]]) G.link(d[x],x);if (~ld[x]&&g[x]==f[ld[x]]) G.link(ld[x],x);if (~rd[x]&&g[x]==f[rd[x]]) G.link(rd[x],x);}}for (int i=pos+1;i<sz;++i){int x=v[p[u].y][i];if (f[u]==g[x]+sz-pos){if (~d[x]&&g[x]==f[d[x]]) G.link(d[x],x);if (~ld[x]&&g[x]==f[ld[x]]) G.link(ld[x],x);if (~rd[x]&&g[x]==f[rd[x]]) G.link(rd[x],x);}}
}
int main(){n=gi();G.cnt=1;for (int i=1;i<=n;++i) p[i]=(node){gi(),gi(),i},o[i]=p[i].y;sort(o+1,o+n+1);len=unique(o+1,o+n+1)-o-1;sort(p+1,p+n+1);memset(d,-1,sizeof(d));M.clear();M[0]=0;for (int i=1;i<=n;++i){if (M.find(p[i].x)!=M.end()) d[p[i].id]=M[p[i].x];M[p[i].x]=p[i].id;}memset(ld,-1,sizeof(ld));M.clear();M[0]=0;for (int i=1;i<=n;++i){if (M.find(p[i].x+p[i].y)!=M.end()) ld[p[i].id]=M[p[i].x+p[i].y];M[p[i].x+p[i].y]=p[i].id;}memset(rd,-1,sizeof(rd));M.clear();M[0]=0;for (int i=1;i<=n;++i){if (M.find(p[i].y-p[i].x)!=M.end()) rd[p[i].id]=M[p[i].y-p[i].x];M[p[i].y-p[i].x]=p[i].id;}for (int i=1;i<=n;++i){p[i].y=lower_bound(o+1,o+len+1,p[i].y)-o;v[p[i].y].push_back(p[i].id);}memset(f,-63,sizeof(f));memset(g,-63,sizeof(g));f[0]=0;for (int i=1;i<=len;++i){int sz=v[i].size(),mx;for (int j=0;j<sz;++j){int x=v[i][j];if (~d[x]) cmax(g[x],f[d[x]]);if (~ld[x]) cmax(g[x],f[ld[x]]);if (~rd[x]) cmax(g[x],f[rd[x]]);cmax(f[x],g[x]+1);}mx=-inf;for (int j=0;j<sz;++j){int x=v[i][j];cmax(f[x],mx+j+1);cmax(mx,g[x]);}mx=-inf;for (int j=sz-1;~j;--j){int x=v[i][j];cmax(f[x],mx+sz-j);cmax(mx,g[x]);}}for (int i=1;i<=n;++i) cmax(ans,f[i]);printf("%d\n",ans);sort(p+1,p+n+1,cmp);for (int i=1;i<=n;++i) if (f[i]==ans) {dfs(i);puts("");break;}for (int i=1;i<=n;++i) if (f[i]==ans) tag[i]=1;for (int i=len;i;--i)for (int j=0,sz=v[i].size();j<sz;++j)if (tag[v[i][j]]) build(v[i][j]);printf("%d\n",G.work());return 0;
}

转载于:https://www.cnblogs.com/zhoushuyu/p/9281144.html

[BZOJ4200][NOI2015]小园丁与老司机相关推荐

  1. P2304 [NOI2015] 小园丁与老司机(网络流/上下界网络流)

    P2304 [NOI2015] 小园丁与老司机 平面上有n个点,每次可以向左.右.上.左上45度.右上45度移动,然后直线移动到达第一个没有到过的点,如果没有这样的点就不能移动,求解一条最长路,然后求 ...

  2. BZOJ4200 洛谷2304 UOJ132:[NOI2015]小园丁与老司机——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4200 https://www.luogu.org/problemnew/show/P2304 ht ...

  3. 提高千倍效率的35个编码小技巧,老司机带你飞!

    点击关注公众号,实用技术文章及时了解 来源:henleylee.github.io/posts/2019/a780fcc1.html 前言 代码优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的 ...

  4. mysql入门到跑路_Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26

    1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis  mongoab  memcache 2. 请简述数据库管理系统的作用 数据存 ...

  5. oracle从删库到跑路,Mysql入门二十小题(DBA老司机带你删库到跑路)2018.11.26

    1. 请介绍数据库管理系统的种类及代表产品 RDBMS: mysql oracle mssql NoSQL: redis  mongoab  memcache 2. 请简述数据库管理系统的作用 数据存 ...

  6. 年薪30W的软件测试“老司机”工作经验

    这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...

  7. 【新梦想学员干货】必看!年薪30W的软件测试“老司机”工作经验。

    这几天,新入职的小MM提议"老司机"们把自己这些年的软件测试工作经验跟大家分享一下,让新同学学习学习,利用空闲时间我整理了一些,可能不全,勉强看看,这也算是对自己这些年的工作总结. ...

  8. 名悦集团:开车从不追尾,老司机分享驾驶避免事故小知识

    听交通广播,我们几乎每天都能听到高速路上,高架桥上,上班路上发生追尾事故,有时候是个平常的上下班高峰期.很多人会纳闷,车开的好好的,怎么就会发生追尾事故呢.开车在路上,难免会有磕磕碰碰.道路千万条,安 ...

  9. 老司机都在用的浏览器,体积小功能齐全,直呼内行

    现在市面上的浏览器简直是多不胜数,虽然数量多,但是好用的并不多.尤其是某些大厂的浏览器,无用的功能越来越多,越来越臃肿,体积也越来越大,使用体验还不好,有时候甚至不如一些小众浏览器.今天给大家安利2款 ...

  10. 视频教程-老司机讲前端之微信小程序开发成语消消乐游戏视频课程-微信开发

    老司机讲前端之微信小程序开发成语消消乐游戏视频课程 中国实战派HTML5培训第一人,微软技术讲师,曾任百合网技术总监,博看文思HTML5总监.陶国荣长期致力于HTML5.JavaScript.CSS3 ...

最新文章

  1. Android中获取手机电量信息
  2. 创建自己的Java批注
  3. matlab r2010a教程,MATLAB教程R2010a(十二五)
  4. 关于C语言中的Bool类型变量的一点看法
  5. ActiveMQ学习总结(6)——ActiveMQ集成Spring和Log4j实现异步日志
  6. 通俗易懂!视觉slam第二部分——salm过程简介
  7. js中字符串正则表达式、正则法则pattern、RegExp、flags、exec
  8. 二级倒立摆建模(二)
  9. 思科模拟器GNS3将路由器变成交换机的方法
  10. 关于nubia z9 NX508J notification 不显示的问题
  11. arctanx麦克劳林公式推导过程_高中数学三角函数公式大全,竞赛高考都适用(含公式推导)...
  12. c语言程序 实现简单计算器功能,C语言实现简单计算器功能(1)
  13. JAVA能写大型游戏么?
  14. 24点游戏 java实现,一个基于Java技术编写的24点游戏逼真图形版,调用了很多图片去显示游戏内容JAVA游戏源码下载...
  15. 王者勋章服务器维护中,【维护】4月1日官方维护公告(抢鲜服)
  16. EasyGBS国标视频云服务平台可以获取录像却无法播放是什么原因?
  17. 有多厉害?首互联网卫星发射 飞机高铁WiFi就靠它了
  18. vue 表单验证正则_vue表单验证
  19. 如何修改pdf文件内容并保存
  20. char类型的取值范围

热门文章

  1. PLC可编程控制实验装置及单片机综合实验台
  2. 大淘客cms源码修改二次开发实现淘京拼三合一功能
  3. 人工智能终究会抢了我们程序员的饭碗
  4. 乱世王者服务器维护,乱世王者微信534区仰不愧天开服时间表_乱世王者新区开服预告_第一手游网手游开服表...
  5. 【HDLBits刷题笔记】Exams/ece241 2013 q7
  6. 系统辨识与自适应控制matlab程序_杂志精选 | 自适应声反馈抑制技术及其应用
  7. DRM 驱动程序开发(VKMS)
  8. SSD-tensorflow-1 demo
  9. 计算机网络共享打不开,电脑系统网络和共享中心打不开怎么办
  10. 【git】基于github开源平台的项目进行二次开发