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,但不适用于pojusing 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-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);inline void clear(vector<int> *A,int a,int b){int i,j;A->clear();re(i,0,a)re(j,0,b)A[i].push_back(0);}inline int gint(){int res=0;bool neg=0;char z;for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());if(z==EOF)return 0;if(z=='-'){neg=1;z=getchar();}for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());return (neg)?-res:res; }
inline LL gll(){LL res=0;bool neg=0;char z;for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());if(z==EOF)return 0;if(z=='-'){neg=1;z=getchar();}for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());return (neg)?-res:res; }const int maxN=50000;
const int INF=1<<30;int N;
struct Tpoint{int x,y,id;}p[maxN+100];
int pos[maxN+100];
PII lr[maxN+100];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+100];
struct Tedge{int v,next;}edge[3*maxN+100];inline void addedge(int u,int v){now++;edge[now].v=v;edge[now].next=first[u];first[u]=now;}int G[maxN+100],F[maxN+100];
int toG[maxN+100],toF[maxN+100];
int isonlyG[maxN+100],isonlyF[maxN+100];inline int walk(int head,int tail,int st,int en){if(st==en) return 0;if(st<en) return en-head; if(st>en) return tail-en;}inline void outputpoint(int x){if(x!=1)PF("%d ",x-1);}
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+1;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-1;x!=en;x--)outputpoint(p[x].id);outputpoint(p[x].id);return;}}
inline void outputway(){int u=1,v;while(u!=-1){v=toF[u];outputwalk(lr[pos[u]].fi,lr[pos[u]].se,pos[u],pos[v]);u=toG[v];}PF("\n");}int flagF[maxN+100],flagG[maxN+100];
vector<int> V[maxN+100];int S,T,superS,superT;
int intot[maxN+100],outtot[maxN+100];
int tol,info[maxN+100];
struct Tedge2{int v,flow,next;}E[10000000];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+1;T=N+2;superS=N+3;superT=N+4;mmst(info,-1);tol=-1;re(i,1,N)re(j,0,int(V[i].size())-1)outtot[i]++,intot[V[i][j]]++;re(i,1,N+2){addedge2(superS,i,intot[i]);addedge2(i,superS,0);addedge2(i,superT,outtot[i]);addedge2(superT,i,0);}re(i,1,N)addedge2(S,i,INF),addedge2(i,S,0);re(i,1,N)addedge2(i,T,INF),addedge2(T,i,0);re(i,1,N)re(j,0,int(V[i].size())-1)addedge2(i,V[i][j],INF),addedge2(V[i][j],i,0);}int level[maxN+100],last[maxN+100];
int head,tail,que[maxN+100];
inline int Dinic_Build(){int i;mmst(level,0);level[que[head=tail=1]=superS]=1;while(head<=tail){int u=que[head++],v,flow;for(i=info[u],v=E[i].v,flow=E[i].flow;i!=-1;i=E[i].next,v=E[i].v,flow=E[i].flow)if(!level[v] && flow>0)level[que[++tail]=v]=level[u]+1;}return level[superT];}
inline int Dinic(int u,int delta){if(u==superT) return delta;int res=0,&i=last[u],v,flow;for(v=E[i].v,flow=E[i].flow;i!=-1;i=E[i].next,v=E[i].v,flow=E[i].flow)if(level[u]+1==level[v] && flow>0){int tmp=Dinic(v,min(delta,flow));delta-=tmp;res+=tmp;E[i].flow-=tmp;E[i^1].flow+=tmp;if(delta==0) return res;}return res;}inline int check(){int u=1;while(u!=-1){if(!isonlyF[u])return 0;u=toF[u];if(!isonlyG[u])return 0;u=toG[u];}int cnt=0,f=0;u=1;while(u!=-1){if(toF[u]!=u) f=0;u=toF[u];if(toG[u]==-1)break;if(!f){cnt++;f=1;}u=toG[u];}PF("%d\n",cnt);return 1;}int main(){freopen("farm.in","r",stdin);freopen("farm.out","w",stdout);int i,j,k;N=gint()+1;p[1].x=0,p[1].y=0,p[1].id=1;re(i,2,N)p[i].x=gint(),p[i].y=gint(),p[i].id=i;mmst(first,-1);now=-1;sort(p+1,p+N+1,cmp2);re(i,2,N)if(p[i].x==p[i-1].x)addedge(p[i].id,p[i-1].id);sort(p+1,p+N+1,cmp3);re(i,2,N)if(p[i].y-p[i].x==p[i-1].y-p[i-1].x)addedge(p[i].id,p[i-1].id);sort(p+1,p+N+1,cmp4);re(i,2,N)if(p[i].y+p[i].x==p[i-1].y+p[i-1].x)addedge(p[i].id,p[i-1].id);sort(p+1,p+N+1,cmp1);re(i,1,N)pos[p[i].id]=i;int head,tail;for(head=1;head<=N;head=tail+1){for(tail=head;tail+1<=N && p[tail+1].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]=1;toG[u]=-1;isonlyG[u]=1;for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(F[v]+1>G[u])G[u]=F[v]+1,toG[u]=v,isonlyG[u]=1;elseif(F[v]+1==G[u]) isonlyG[u]=0;F[u]=G[u],toF[u]=u,isonlyF[u]=1;}/*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=0,tot=0,isonly=1;re(j,head+1,tail){int u=p[j].id,v=p[j-1].id;if(G[v]+tail-(j-1)>t)t=G[v]+tail-(j-1),tot=v,isonly=1;elseif(G[v]+tail-(j-1)==t) isonly=0;if(t>F[u])F[u]=t,toF[u]=tot,isonlyF[u]=isonly;elseif(t==F[u])if(isonly==0)isonlyF[u]=0;}t=0,tot=0,isonly=1;red(j,tail-1,head){int u=p[j].id,v=p[j+1].id;if(G[v]+j+1-head>t)t=G[v]+j+1-head,tot=v,isonly=1;elseif(G[v]+j+1-head==t) isonly=0;if(t>F[u])F[u]=t,toF[u]=tot,isonlyF[u]=isonly;elseif(t==F[u])if(isonly==0)isonlyF[u]=0;}}cout<<F[1]-1<<endl;outputway();if(check())return 0;mmst(flagG,0);mmst(flagF,0);flagF[1]=1;for(tail=N;tail>=1;tail=head-1){for(head=tail;head-1>=1 && p[head-1].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]=1;}}re(j,head,tail)if(flagG[p[j].id]){int u=p[j].id,v;for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(F[v]+1==G[u])V[u].push_back(v),flagF[v]=1;}}Flow_build();int fullflow=0,maxflow=0,v,flow;for(i=info[superS],v=E[i].v,flow=E[i].flow;i!=-1;i=E[i].next,v=E[i].v,flow=E[i].flow)fullflow+=flow;while(Dinic_Build()){re(i,1,N+4)last[i]=info[i];maxflow+=Dinic(superS,INF);}cout<<fullflow-maxflow<<endl;return 0;}

View Code

转载于:https://www.cnblogs.com/maijing/p/4689740.html

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. 征途堆积出友情的永恒「堆优化dp」
  2. linux usr g 空间不足,centos 磁盘空间不足
  3. 2021肿瘤学,所有SCI期刊都在这里
  4. JavaScript ECMA
  5. HashMap两种遍历数据的方式
  6. python字典怎么设置_在python中设置字典中的属性
  7. 拼多多算法笔试2020
  8. Android:通过startActivityForResult方法来得到Activity的回传值
  9. X5档案-参加业务架构平台研讨会后记
  10. python 二分查找法
  11. 【vscode】程序员居然用vscode听网易云
  12. 深入浅出vuejspdf下载_vue下载pdf
  13. tableau中快速实现环比增长率计算
  14. H5标签 marquee 滚动字幕
  15. Java实验:教练和运动员案例
  16. 15.9 文本查询程序再探(继承)
  17. 波卡Polkadot
  18. 积分运营系列—一款优秀积分商城产品需具备的准则与功能梳理
  19. ArcGIS利用draw绘图工具绘制shp文件
  20. 并发容器J.U.C -- AQS组件(一)

热门文章

  1. iOS活体人脸识别的Demo和一些思路
  2. android毫秒数转换为时分秒,如何将毫秒转换成单独的时分秒的形式?
  3. Toast的几种用法
  4. Reflection conclusion
  5. {转载}与我十年长跑的女朋友就要嫁人了。
  6. -转载-我要我们在一起故事原著
  7. 网站被攻击怎么办如何解决
  8. 详细解读 SQL 窗口函数
  9. 从全面了解高级计量经济学体系+stata实操+实证研究前沿+论文+大数据机器学习+空间计量......._Stata高级计量经济学 陈强
  10. python课本图片_python爬虫当当网python书籍图片