1. 程式人生 > >bzoj 1711 Dining吃飯 —— 最大流

bzoj 1711 Dining吃飯 —— 最大流

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=1711

食物一列,牛拆點,飲料一列。

程式碼如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const xn=405,xm=6e4+5,inf=1e9;
int n,F,D,S,T,hd[xn],ct=1,nxt[xm],to[xm],c[xm],dis[xn],cur[xn];
queue
<int>q; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return f?ret:-ret; } void ade(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct; c[ct]=z;} void add(int x,int
y,int z){ade(x,y,z); ade(y,x,0);} int id(int x,int t)//F,n1,n2,D {if(t==0)return x; if(t==1)return F+x; if(t==2)return F+n+x; if(t==3)return F+n+n+x;} bool bfs() { memset(dis,0,sizeof dis); dis[S]=1; q.push(S); while(q.size()) { int x=q.front(); q.pop(); for(int i=hd[x],u;i;i=nxt[i])
if(!dis[u=to[i]]&&c[i])dis[u]=dis[x]+1,q.push(u); } return dis[T]; } int dfs(int x,int fl) { if(x==T)return fl; int ret=0; for(int &i=cur[x],u;i;i=nxt[i]) { if(dis[u=to[i]]!=dis[x]+1||!c[i])continue; int tmp=dfs(u,min(fl-ret,c[i])); if(!tmp)dis[u]=0; c[i]-=tmp; c[i^1]+=tmp; ret+=tmp; if(ret==fl)break; } return ret; } int main() { n=rd(),F=rd(),D=rd(); S=0; T=(n<<1)+F+D+1; for(int i=1;i<=F;i++)add(S,id(i,0),1); for(int i=1;i<=D;i++)add(id(i,3),T,1); for(int i=1;i<=n;i++)add(id(i,1),id(i,2),1); for(int i=1,f,d,x;i<=n;i++) { f=rd(); d=rd(); for(int j=1;j<=f;j++)x=rd(),add(id(x,0),id(i,1),1); for(int j=1;j<=d;j++)x=rd(),add(id(i,2),id(x,3),1); } int ans=0; while(bfs()) { memcpy(cur,hd,sizeof hd); ans+=dfs(S,inf); } printf("%d\n",ans); return 0; }