1. 程式人生 > >【BZOJ】1711: [Usaco2007 Open]Dining吃飯

【BZOJ】1711: [Usaco2007 Open]Dining吃飯

play push scanf truct int urn ont rst 題解

【算法】最大流

【題解】

S連向食物連向牛連向牛‘連向飲料連向T。

經典的一個元素依賴於兩個元素的建圖方式。

技術分享
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=100010,inf=0x3f3f3f3f;
struct edge{int v,flow,from;}e[maxn];
int first[maxn],d[maxn],cur[maxn],tot=1,S,T,n,A,B;
void insert(int
u,int v,int w){//printf("%d %d\n",u,v); tot++;e[tot].v=v;e[tot].flow=w;e[tot].from=first[u];first[u]=tot; tot++;e[tot].v=u;e[tot].flow=0;e[tot].from=first[v];first[v]=tot; } queue<int>q; bool bfs(){ memset(d,-1,sizeof(d)); d[S]=0;q.push(S); while(!q.empty()){ int x=q.front();q.pop();
for(int i=first[x];i;i=e[i].from) if(e[i].flow&&d[e[i].v]==-1){ d[e[i].v]=d[x]+1; q.push(e[i].v); } } return d[T]!=-1; } int dinic(int x,int a){ if(x==T||a==0)return a; int flow=0,f; for(int& i=cur[x];i;i=e[i].from) if(e[i].flow&&d[e[i].v]==d[x]+1
&&(f=dinic(e[i].v,min(e[i].flow,a)))>0){ e[i].flow-=f; e[i^1].flow+=f; a-=f; flow+=f; if(a==0)break; } return flow; } int main(){ scanf("%d%d%d",&n,&A,&B); S=0;T=A+n+n+B+1; int u,v,w; for(int i=1;i<=A;i++)insert(S,i,1); for(int i=1;i<=B;i++)insert(A+n+n+i,T,1); for(int i=1;i<=n;i++){ scanf("%d%d",&u,&v); for(int j=1;j<=u;j++){ scanf("%d",&w); insert(w,A+i,1); } for(int j=1;j<=v;j++){ scanf("%d",&w); insert(A+n+i,A+n+n+w,1); } insert(A+i,A+n+i,1); } int ans=0; while(bfs()){ for(int i=S;i<=T;i++)cur[i]=first[i]; ans+=dinic(S,inf); } printf("%d",ans); return 0; }
View Code

【BZOJ】1711: [Usaco2007 Open]Dining吃飯