Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special Judge

Description

  小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面。田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2,3,…,n,每棵树可以看作平面上的一个点,其中第 ii 棵树 (1≤i≤n1≤i≤n) 位于坐标 (xi,yi)(xi,yi)。任意两棵树的坐标均不相同。
  老司机 Mr. P 从原点 (0,0)(0,0) 驾车出发,进行若干轮行动。每一轮,Mr. P 首先选择任意一个满足以下条件的方向:
  为左、右、上、左上 45∘45∘ 、右上 45∘45∘ 五个方向之一。
  沿此方向前进可以到达一棵他尚未许愿过的树。
  完成选择后,Mr. P 沿该方向直线前进,必须到达该方向上距离最近的尚未许愿的树,在树下许愿并继续下一轮行动。如果没有满足条件的方向可供选择,则停止行动。他会采取最优策略,在尽可能多的树下许愿。若最优策略不唯一,可以选择任意一种。
  不幸的是,小园丁 Mr. S 发现由于田野土质松软,老司机 Mr. P 的小汽车在每轮行进过程中,都会在田野上留下一条车辙印,一条车辙印可看作以两棵树(或原点和一棵树)为端点的一条线段。
  在 Mr. P 之后,还有很多许愿者计划驾车来田野许愿,这些许愿者都会像 Mr. P 一样任选一种最优策略行动。Mr. S 认为非左右方向(即上、左上 45∘45∘ 、右上 45∘45∘ 三个方向)的车辙印很不美观,为了维护田野的形象,他打算租用一些轧路机,在这群许愿者到来之前夯实所有“可能留下非左右方向车辙印”的地面。
  “可能留下非左右方向车辙印”的地面应当是田野上的若干条线段,其中每条线段都包含在某一种最优策略的行进路线中。每台轧路机都采取满足以下三个条件的工作模式:
  从原点或任意一棵树出发。
  只能向上、左上 45∘45∘ 、右上 45∘45∘ 三个方向之一移动,并且只能在树下改变方向或停止。
  只能经过“可能留下非左右方向车辙印”的地面,但是同一块地面可以被多台轧路机经过。
  现在 Mr. P 和 Mr. S 分别向你提出了一个问题:
  请给 Mr .P 指出任意一条最优路线。
  请告诉 Mr. S 最少需要租用多少台轧路机。

Input

  输入文件的第 1 行包含 1 个正整数 n,表示许愿树的数量。

  接下来 n 行,第 i+1 行包含 2个整数 xi,yi,中间用单个空格隔开,表示第 i 棵许愿树的坐标。

Output

  输出文件包括 3 行。
  输出文件的第 1 行输出 1 个整数 m,表示 Mr. P 最多能在多少棵树下许愿。
  输出文件的第 2 行输出 m 个整数,相邻整数之间用单个空格隔开,表示 Mr. P 应该依次在哪些树下许愿。
  输出文件的第 3 行输出 1 个整数,表示 Mr. S 最少需要租用多少台轧路机。

Sample Input

  6
  -1 1
  1 1
  -2 2
  0 8
  0 9
  0 10

Sample Output

  3
  2 1 3
  3

Hint

  explanation
  最优路线 2 条可许愿 3 次:(0,0)→(1,1)→(−1,1)→(−2,2)(0,0)→(1,1)→(−1,1)→(−2,2) 或 (0,0)→(0,8)→(0,9)→(0,10)(0,0)→(0,8)→(0,9)→(0,10)。 至少 3 台轧路机,路线是 (0,0)→(1,1)(0,0)→(1,1),(−1,1)→(−2,2)(−1,1)→(−2,2) 和 (0,0)→(0,8)→(0,9)→(0,10)(0,0)→(0,8)→(0,9)→(0,10)。

Solution

  把坐标分别按x,y,x+y,x-y排序即可求出一个点向各个方向能到的点,然后DP求出从原点到一个点最多经过的点数,状态有两种情况,一种是从y坐标小的转移过来,一种是从y坐标相同的转移过来,两种最好分开考虑,细节可能有点多。DP完求出转移路径即可解决第一问,第二问要我们求出最少用几条链才能覆盖所有可能在最优路径上的y坐标增大的边,求出这些边后我们可以用带下界的最小流解决(理解最小流后建图比较容易)。

Solution

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
inline int read()
{
int x,f=;char c;
while((c=getchar())<''||c>'')if(c=='-')f=;
for(x=c-'';(c=getchar())>=''&&c<='';)x=x*+c-'';
return f?x:-x;
}
#define MN 50000
#define MV 50002
#define ME 250000
#define S MV+1
#define T MV+2
#define INF 0x3FFFFFFF
struct node{int x,y,id;}p[MN+];
bool cmp1(const node&a,const node&b){return a.x+a.y==b.x+b.y?a.y<b.y:a.x+a.y<b.x+b.y;}
bool cmp2(const node&a,const node&b){return a.x-a.y==b.x-b.y?a.y<b.y:a.x-a.y<b.x-b.y;}
bool cmp3(const node&a,const node&b){return a.x==b.x?a.y<b.y:a.x<b.x;}
bool cmp4(const node&a,const node&b){return a.y==b.y?a.x<b.x:a.y<b.y;}
int s[MN+],t1[MN+],t2[MN+],t3[MN+],l[MN+],r[MN+],f[MN+],ff[MN+],lf[MN+],rf[MN+],a[MN+],an;
vector<int> v,t[MN+];
namespace maxFlow
{
struct edge{int nx,t,w;}e[ME*+];
int h[MV+],en=,d[MV+],c[MV+],q[MV+],qn;
inline void ins(int x,int y,int w)
{
e[++en]=(edge){h[x],y,w};h[x]=en;
e[++en]=(edge){h[y],x,};h[y]=en;
}
bool bfs()
{
int i,j;
memset(d,,sizeof(d));
for(d[q[i=qn=]=S]=;i<=qn;++i)for(j=c[q[i]]=h[q[i]];j;j=e[j].nx)
if(e[j].w&&!d[e[j].t])d[q[++qn]=e[j].t]=d[q[i]]+;
return d[T];
}
int dfs(int x,int r)
{
if(x==T)return r;
int k,u=;
for(int&i=c[x];i;i=e[i].nx)if(e[i].w&&d[e[i].t]==d[x]+)
{
k=dfs(e[i].t,min(e[i].w,r-u));
u+=k;e[i].w-=k;e[i^].w+=k;
if(u==r)return u;
}
return d[x]=,u;
}
int dinic(){int res=;while(bfs())res+=dfs(S,INF);return res;}
}
void upd(int x,int y)
{
if(ff[y]+>f[x])f[x]=ff[y]+,t[x].clear();
if(ff[y]+==f[x])t[x].push_back(y);
}
void get_ans(int x)
{
a[++an]=x;
int i,j,u=;
if(f[x]==ff[x]){u=;if(p[x].id)get_ans(t[x][]);}
for(i=l[x];u&&i<x;++i)if(f[i]+x-l[x]==ff[x])
{
u=;
for(j=x;--j>i;)a[++an]=j;
for(j=l[x];j<=i;++j)a[++an]=j;
if(p[i].id)get_ans(t[i][]);
}
for(i=r[x];u&&i>x;--i)if(f[i]+r[x]-x==ff[x])
{
u=;
for(j=x;++j<i;)a[++an]=j;
for(j=r[x];j>=i;--j)a[++an]=j;
if(p[i].id)get_ans(t[i][]);
}
}
int d[MN+],u[MN+],c[MN+];
inline void ins(int x,int y){maxFlow::ins(x,y,INF);++c[x];--c[y];}
void dfs(int x)
{
if(d[x])return;
int i,j;d[x]=;
if(f[x]==ff[x]&&!u[x])for(u[x]=,i=;i<t[x].size();++i)ins(t[x][i],x),dfs(t[x][i]);
for(i=l[x];i<x;++i)if(f[i]+x-l[x]==ff[x]&&!u[i])for(u[i]=,j=;j<t[i].size();++j)ins(t[i][j],i),dfs(t[i][j]);
for(i=r[x];i>x;--i)if(f[i]+r[x]-x==ff[x]&&!u[i])for(u[i]=,j=;j<t[i].size();++j)ins(t[i][j],i),dfs(t[i][j]);
}
int main()
{
int n=read(),i,j,ans=;
for(i=;i<=n;++i)p[i].x=read(),p[i].y=read(),p[i].id=i;
sort(p,p+n+,cmp1);
for(i=;i<n;++i)if(p[i].x+p[i].y==p[i+].x+p[i+].y)t1[p[i].id]=p[i+].id;
sort(p,p+n+,cmp2);
for(i=;i<n;++i)if(p[i].x-p[i].y==p[i+].x-p[i+].y)t2[p[i].id]=p[i+].id;
sort(p,p+n+,cmp3);
for(i=;i<n;++i)if(p[i].x==p[i+].x)t3[p[i].id]=p[i+].id;
sort(p,p+n+,cmp4);
for(i=;i<=n;++i)s[p[i].id]=i;
memset(f,,sizeof(f));f[s[]]=;
for(i=;i<=n;i=r[i]+)
{
for(l[i]=r[i]=i;r[i]<n&&p[r[i]+].y==p[r[i]].y;++r[i]);
for(j=l[i];++j<=r[i];)l[j]=l[i],r[j]=r[i];
for(lf[l[i]]=-INF,j=l[i];++j<=r[i];)lf[j]=max(lf[j-],f[j-]);
for(rf[r[i]]=-INF,j=r[i];--j>=l[i];)rf[j]=max(rf[j+],f[j+]);
for(j=l[i];j<=r[i];++j)
{
ff[j]=max(f[j],max(lf[j]+j-l[i],rf[j]+r[i]-j));
if(t1[p[j].id])upd(s[t1[p[j].id]],j);
if(t2[p[j].id])upd(s[t2[p[j].id]],j);
if(t3[p[j].id])upd(s[t3[p[j].id]],j);
if(ff[j]>ans)ans=ff[j],v.clear();
if(ff[j]==ans)v.push_back(j);
}
}
printf("%d\n",ans);
get_ans(v[]);
for(i=an;--i;)printf("%d ",p[a[i]].id);puts("");
for(i=;i<v.size();++i)dfs(v[i]);
for(i=;i<=n;++i)
{
if(c[i]<)maxFlow::ins(S,i,-c[i]);else maxFlow::ins(i,T,c[i]);
maxFlow::ins(MN+,i,INF);maxFlow::ins(i,MN+,INF);
}
maxFlow::dinic();
maxFlow::ins(MN+,MN+,INF);
printf("%d",maxFlow::dinic());
}

[BZOJ]4200: [Noi2015]小园丁与老司机的更多相关文章

  1. bzoj 4200: [Noi2015]小园丁与老司机【dp+有上下界最小流】

    洛谷上有个点死活卡不过去,不知道是哪里写丑了orz 参考:https://www.cnblogs.com/ditoly/p/BZOJ4200.html 从上往下dp,设f为不向左右走直接上去的值,g为 ...

  2. [BZOJ4200][Noi2015]小园丁与老司机

    4200: [Noi2015]小园丁与老司机 Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 106  Solved ...

  3. [UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机

    [UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机 试题描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 \(n\) 棵许愿 ...

  4. 【BZOJ4200】[Noi2015]小园丁与老司机 DP+最小流

    [BZOJ2839][Noi2015]小园丁与老司机 Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2, ...

  5. luogu P2304 [NOI2015]小园丁与老司机 dp 上下界网络流

    LINK:小园丁与老司机 苦心人 天不负 卧薪尝胆 三千越甲可吞吴 AC的刹那 真的是泪目啊 很久以前就写了 当时记得特别清楚 写到肚子疼.. 调到胳膊疼.. ex到根不不想看的程度. 当时wa了 一 ...

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

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

  7. [Noi2015]小园丁和老司机

    来自FallDream的博客,未经允许,请勿转载,谢谢. 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有n棵许愿树,编号1,2,3,…,n,每棵树可以看作平面上的一个点,其中 ...

  8. uoj132/BZOJ4200/洛谷P2304 [Noi2015]小园丁与老司机 【dp + 带上下界网络流】

    题目链接 uoj132 题解 真是一道大码题,,,肝了一个上午 老司机的部分是一个\(dp\),观察点是按\(y\)分层的,而且按每层点的上限来看可以使用\(O(nd)\)的\(dp\),其中\(d\ ...

  9. 【bzoj4200】[Noi2015]小园丁与老司机 STL-map+dp+有上下界最小流

    题目描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 nn 棵许愿树,编号 1,2,3,…,n1,2,3,…,n,每棵树可以看作平面上的一个点,其中第 ii 棵树 (1≤ ...

随机推荐

  1. poj2029 Get Many Persimmon Trees

    http://poj.org/problem?id=2029 单点修改 矩阵查询 二维线段树 #include<cstdio> #include<cstring> #inclu ...

  2. 超绚丽CSS3多色彩发光立方体旋转动画

    CSS3添加了几个动画效果的属性,通过设置这些属性,可以做出一些简单的动画效果而不需要再去借助JavaScript.css3动画的属性主要分为三类:transform.transition以及anim ...

  3. 开始使用HTML5和CSS3验证表单

    使用HTML5和CSS3验证表单 客户端验证是网页客户端程序最常用的功能之一,我们之前使用了各种各样的js库来进行表单的验证.HTML5其实早已为我们提供了表单验证的功能.至于为啥没有流行起来估计是兼 ...

  4. Android广播发送失败

    现在至今为止Android 8.0 不支持大部分广播收发 如果无法使用建议换至Android 7.0版本 且 minSdkVersion 24

  5. JAVA_SE基础——68.RunTime类

    RunTime类代表Java程序的运行时环境,每一个Java程序都有一个与之对应的Runtime实例,应用程序通过该对象与运行时环境相连,应用程序不能创建自己的Runtime实例,但可以通过getRu ...

  6. Linq 等式运算符:SequenceEqual

    检查元素的数量,每个元素的值及两个集合中元素的顺序是否相等,3个方面都相等则为true,否则为false IList<string> strList1 = new List<stri ...

  7. 20165230 2017-2018-2 《Java程序设计》第4周学习总结

    20165230 2017-2018-2 <Java程序设计>第4周学习总结 教材学习内容总结 子类与继承 通过class 子类名 extends 父类名定义子类.子类只能继承一个父类,关 ...

  8. JavaScript 原型中的哲学思想

    学习JavaScript过程中,原型问题一直让我疑惑许久,那时候捧着那本著名的红皮书,看到有关原型的讲解时,总是心存疑虑.当在JavaScript世界中走过不少旅程之后,再次萌发起研究这部分知识的欲望 ...

  9. SpringCloud的部署模型

    http://www.th7.cn/Program/java/201608/919853.shtml

  10. 新概念英语(1-13)A new dress

    What colour is Anna's hat? A:What colour is your new dress? B:It's green.Come upstairs and see it. A ...