http://uoj.ac/problem/132

这道题前2行的输出比较容易,就是简单的动态规划,然后第3行就是比较少见的有上下界的最小流。

前2行比较容易,我们讨论一下第3行的解法吧。

比如第1个样例:

我们先找出那些可能成为最优解的非平行边:

Case11~14做法:

这里保证存在一种最优解,使得轧路机不重复经过同一路面。

我们求出每个点i的入度in[i]和出度out[i]。

然后就是∑max(in[i]-out[i],0)。

我们可以这样想,

当in[i]>out[i]时,必定有in[i]-out[i]条路径在i号点结束。

当in[i]<=out[i]时,一定不会有路径在i号点结束。

其实就是统计在每个点结束的路径个数。

好神奇。。。。。。

100%做法:

其实就是设源点S和汇点T,源点S向所有点连一条下界为0,上界为+oo的边;所有点向汇点T连一条下界为0,上界为+oo的边;原图中边为下界为1,上界为+oo的边,然后求S到T的最小流。

其实就是这样(不妨用(a,b)表示边的下界为a,上界为b):

(图丑勿喷)

然后求有上下界的最小流。

求有上下界的最小流的做法是:

建立superS和superT;

in[i]表示i号点入边的下界和。

out[i]表示i号点出边的下界和。

superS连向每个点i一条容量为in[i]的边;每个点i连向superT一条容量为out[i]边;

原图的边的容量变成为上界-下界。

先不连S到T,求superS到superT的最大流。然后再连S到T一条容量为INF的边,再求supperS到superT的最大流,如果满流,则第二次增广的就是原图的最小流,其实就是满流减去第一次做的最大流。否则无解。

但这道题是肯定有解的,所以不用第二次增广,直接满流-第一次增广得到的最大流。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline void clear(vector<int> *A,int a,int b){int i,j;A->clear();re(i,,a)re(j,,b)A[i].push_back();} inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const int INF=<<; int N;
struct Tpoint{int x,y,id;}p[maxN+];
int pos[maxN+];
PII lr[maxN+]; inline bool cmp1(Tpoint a,Tpoint b){return (a.y!=b.y)?a.y>b.y:a.x<b.x;}
inline bool cmp2(Tpoint a,Tpoint b){return (a.x!=b.x)?a.x<b.x:a.y>b.y;}
inline bool cmp3(Tpoint a,Tpoint b){return (a.y-a.x!=b.y-b.x)?a.y-a.x<b.y-b.x:a.x>b.x;}
inline bool cmp4(Tpoint a,Tpoint b){return (a.y+a.x!=b.y+b.x)?a.y+a.x<b.y+b.x:a.x<b.x;} int now,first[maxN+];
struct Tedge{int v,next;}edge[*maxN+]; inline void addedge(int u,int v)
{
now++;
edge[now].v=v;
edge[now].next=first[u];
first[u]=now;
} int G[maxN+],F[maxN+];
int toG[maxN+],toF[maxN+];
int isonlyG[maxN+],isonlyF[maxN+]; inline int walk(int head,int tail,int st,int en)
{
if(st==en) return ;
if(st<en) return en-head;
if(st>en) return tail-en;
} inline void outputpoint(int x){if(x!=)PF("%d ",x-);}
inline void outputwalk(int head,int tail,int st,int en)
{
int x;
if(st==en)
{
outputpoint(p[st].id);
return;
}
if(st<en)
{
for(x=st;x!=head;x--)outputpoint(p[x].id);
outputpoint(p[x].id);
for(x=st+;x!=en;x++)outputpoint(p[x].id);
outputpoint(p[x].id);
return;
}
if(st>en)
{
for(x=st;x!=tail;x++)outputpoint(p[x].id);
outputpoint(p[x].id);
for(x=st-;x!=en;x--)outputpoint(p[x].id);
outputpoint(p[x].id);
return;
}
}
inline void outputway()
{
int u=,v;
while(u!=-)
{
v=toF[u];
outputwalk(lr[pos[u]].fi,lr[pos[u]].se,pos[u],pos[v]);
u=toG[v];
}
PF("\n");
} int flagF[maxN+],flagG[maxN+];
vector<int> V[maxN+]; int S,T,superS,superT;
int intot[maxN+],outtot[maxN+];
int tol,info[maxN+];
struct Tedge2{int v,flow,next;}E[]; inline void addedge2(int u,int v,int flow)
{
tol++;
E[tol].v=v;
E[tol].flow=flow;
E[tol].next=info[u];
info[u]=tol;
} inline void Flow_build()
{
int i,j;
S=N+;T=N+;superS=N+;superT=N+;
mmst(info,-);tol=-;
re(i,,N)re(j,,int(V[i].size())-)outtot[i]++,intot[V[i][j]]++;
re(i,,N+)
{
addedge2(superS,i,intot[i]);addedge2(i,superS,);
addedge2(i,superT,outtot[i]);addedge2(superT,i,);
}
re(i,,N)
addedge2(S,i,INF),addedge2(i,S,);
re(i,,N)
addedge2(i,T,INF),addedge2(T,i,);
re(i,,N)re(j,,int(V[i].size())-)
addedge2(i,V[i][j],INF),addedge2(V[i][j],i,);
} int level[maxN+],last[maxN+];
int head,tail,que[maxN+];
inline int Dinic_Build()
{
int i;
mmst(level,);
level[que[head=tail=]=superS]=;
while(head<=tail)
{
int u=que[head++],v,flow;
for(i=info[u],v=E[i].v,flow=E[i].flow;i!=-;i=E[i].next,v=E[i].v,flow=E[i].flow)
if(!level[v] && flow>)level[que[++tail]=v]=level[u]+;
}
return level[superT];
}
inline int Dinic(int u,int delta)
{
if(u==superT) return delta;
int res=,&i=last[u],v,flow;
for(v=E[i].v,flow=E[i].flow;i!=-;i=E[i].next,v=E[i].v,flow=E[i].flow)
if(level[u]+==level[v] && flow>)
{
int tmp=Dinic(v,min(delta,flow));
delta-=tmp;
res+=tmp;
E[i].flow-=tmp;
E[i^].flow+=tmp;
if(delta==) return res;
}
return res;
} inline int check()
{
int u=;
while(u!=-)
{
if(!isonlyF[u])return ;
u=toF[u];
if(!isonlyG[u])return ;
u=toG[u];
}
int cnt=,f=;
u=;
while(u!=-)
{
if(toF[u]!=u) f=;
u=toF[u];
if(toG[u]==-)break;
if(!f){cnt++;f=;}
u=toG[u];
}
PF("%d\n",cnt);
return ;
} int main()
{
freopen("farm.in","r",stdin);
freopen("farm.out","w",stdout);
int i,j,k;
N=gint()+;
p[].x=,p[].y=,p[].id=;
re(i,,N)p[i].x=gint(),p[i].y=gint(),p[i].id=i; mmst(first,-);now=-;
sort(p+,p+N+,cmp2);
re(i,,N)if(p[i].x==p[i-].x)addedge(p[i].id,p[i-].id);
sort(p+,p+N+,cmp3);
re(i,,N)
if(p[i].y-p[i].x==p[i-].y-p[i-].x)
addedge(p[i].id,p[i-].id);
sort(p+,p+N+,cmp4);
re(i,,N)if(p[i].y+p[i].x==p[i-].y+p[i-].x)addedge(p[i].id,p[i-].id); sort(p+,p+N+,cmp1);
re(i,,N)pos[p[i].id]=i;
int head,tail;
for(head=;head<=N;head=tail+)
{
for(tail=head;tail+<=N && p[tail+].y==p[head].y;tail++);
re(j,head,tail)lr[j]=PII(head,tail);
re(j,head,tail)
{
int u=p[j].id,v;
G[u]=;toG[u]=-;isonlyG[u]=;
for(i=first[u],v=edge[i].v;i!=-;i=edge[i].next,v=edge[i].v)
if(F[v]+>G[u])
G[u]=F[v]+,toG[u]=v,isonlyG[u]=;
else
if(F[v]+==G[u]) isonlyG[u]=;
F[u]=G[u],toF[u]=u,isonlyF[u]=;
}
/*re(j,head,tail)
{
int u=p[j].id;
F[u]=G[u];toF[u]=u;
re(k,head,tail)
{
int v=p[k].id,dis=walk(head,tail,j,k);
if(G[v]+dis>F[u])F[u]=G[v]+dis,toF[u]=v;
}
}*/
int t=,tot=,isonly=;
re(j,head+,tail)
{
int u=p[j].id,v=p[j-].id;
if(G[v]+tail-(j-)>t)
t=G[v]+tail-(j-),tot=v,isonly=;
else
if(G[v]+tail-(j-)==t) isonly=;
if(t>F[u])
F[u]=t,toF[u]=tot,isonlyF[u]=isonly;
else
if(t==F[u])
if(isonly==)
isonlyF[u]=;
}
t=,tot=,isonly=;
red(j,tail-,head)
{
int u=p[j].id,v=p[j+].id;
if(G[v]+j+-head>t)
t=G[v]+j+-head,tot=v,isonly=;
else
if(G[v]+j+-head==t) isonly=;
if(t>F[u])
F[u]=t,toF[u]=tot,isonlyF[u]=isonly;
else
if(t==F[u])
if(isonly==)
isonlyF[u]=;
}
} cout<<F[]-<<endl;
outputway(); if(check())return ; mmst(flagG,);mmst(flagF,);
flagF[]=;
for(tail=N;tail>=;tail=head-)
{
for(head=tail;head->= && p[head-].y==p[tail].y;head--);
re(j,head,tail)if(flagF[p[j].id])
{
int u=p[j].id;
re(k,head,tail)
{
int v=p[k].id,dis=walk(head,tail,j,k);
if(G[v]+dis==F[u])flagG[v]=;
}
}
re(j,head,tail)if(flagG[p[j].id])
{
int u=p[j].id,v;
for(i=first[u],v=edge[i].v;i!=-;i=edge[i].next,v=edge[i].v)
if(F[v]+==G[u])
V[u].push_back(v),flagF[v]=;
}
} Flow_build();
int fullflow=,maxflow=,v,flow;
for(i=info[superS],v=E[i].v,flow=E[i].flow;i!=-;i=E[i].next,v=E[i].v,flow=E[i].flow)fullflow+=flow;
while(Dinic_Build())
{
re(i,,N+)last[i]=info[i];
maxflow+=Dinic(superS,INF);
}
cout<<fullflow-maxflow<<endl;
return ;
}

NOI2015 小园丁与老司机的更多相关文章

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

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

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

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

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

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

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

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

  5. [BZOJ]4200: [Noi2015]小园丁与老司机

    Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special Judge Description 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维 ...

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

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

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

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

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

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

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

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

  10. 【洛谷2304_LOJ2134】[NOI2015]小园丁与老司机(动态规划_网络流)

    题目: 洛谷 2304 LOJ 2134 (LOJ 上每个测试点有部分分) 写了快一天 -- 好菜啊 分析: 毒瘤二合一题 -- 注意本题(及本文)使用 \(x\) 向右,\(y\) 向上的「数学坐标 ...

随机推荐

  1. Java[3] Java多线程相关资料

    Java多线程: http://www.uml.org.cn/j2ee/201509093.asp

  2. iOS中XMPP简单聊天实现 好友和聊天

    版权声明本文由陈怀哲首发自简书:http://www.jianshu.com/users/9f2e536b78fd/latest_articles;微信公众号:陈怀哲(chenhuaizhe2016) ...

  3. [转]Android Volley完全解析(四),带你从源码的角度理解Volley

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是 ...

  4. [置顶] Android访问控制系统测试与评估

    5.1实验方案 通过以上章节,本文阐述了目前Android平台上的恶意软件以“隐私窃取”和“恶意扣费”类为主,本研究课题访问控制的目标也正是阻止恶意软件“隐私窃取”和“恶意扣费”的行为,因此,本实验方 ...

  5. 开发专题指南: JEECG高速微云开发平台前言

    JEECG微云高速开发平台-前言 1. 前言 1.1. 技术背景 随着WEB UI 框架(EasyUI/Jquery UI/Ext/DWZ)等的逐渐成熟,系统界面逐渐实现统一化,代码生成器也能够生成统 ...

  6. C++类的const成员函数、默认的构造函数、复制形参调用函数(转)

    C++类的const成员函数 double Sales_item::avg_price() const { } const关键字表明这是一个const成员函数,它不可以修改Sales_item类的成员 ...

  7. Mysql数据库里面的String类型依照数字来排序以及按时间排序的sql语句

    今天做项目的时候,遇到个小小的问题,在数据库中查询的时候,要用String类型的ID进行一下排序!(注:ID字段为 varchar 类型) 解决的方法: 如: SELECT * FROM  Stude ...

  8. xml的加密和解密

    xml加密(XML Encryption)是w3c加密xml的标准.这个加密过程包括加密xml文档的元素及其子元素,通过加密,xml的初始内容将被替换,但其xml格式仍然被完好的保留. 介绍我们有3个 ...

  9. 一年后重翻javascript

      回想下自己的工作历程  一年多的ios开发眨眼间就过去了  不过这一切还没有结束,紧随其后的便是前段开发,虽然顶点基础都没有,但是还是通过我的不懈努力最终成功转型,虽然刚开始是通过jq直接入门的 ...

  10. $_SERVER变量 以及 PHP 使用 $_SERVER['PHP_SELF'] 获取当前页面地址及其安全性问题

    PHP $_SERVER['PHP_SELF'] $_SERVER['PHP_SELF'] 表示当前 php 文件相对于网站根目录的位置地址,与 document root 相关. 假设我们有如下网址 ...