您的位置:首页 > 其它

NOI2015 小园丁与老司机

2015-07-30 16:28 323 查看
http://uoj.ac/problem/132

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

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

比如第1个样例:

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

#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-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;
else
if(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;
else
if(G[v]+tail-(j-1)==t) isonly=0;
if(t>F[u])
F[u]=t,toF[u]=tot,isonlyF[u]=isonly;
else
if(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;
else
if(G[v]+j+1-head==t) isonly=0;
if(t>F[u])
F[u]=t,toF[u]=tot,isonlyF[u]=isonly;
else
if(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: