[BZOJ1711][Usaco2007 Open]Dining吃饭(最大流)

来源:互联网 发布:linux jira安装配置 编辑:程序博客网 时间:2024/05/21 09:28

题目描述

传送门

题解

对于每一个食物ai,s->ai,1
对于每一个饮料bi,bi->t,1
对于每一头牛,拆点ci->di,1
对于每一头牛选择的食物和饮料ai->ci,di->bi

代码

#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;const int max_n=105;const int max_N=max_n*5;const int max_m=max_N*max_N;const int max_e=max_m*2;const int INF=1e9;int n,f,d,N,F,D,fi,di,maxflow;int tot,point[max_N],nxt[max_e],v[max_e],remain[max_e];int deep[max_N],last[max_N],num[max_N],cur[max_N];queue <int> q;inline void addedge(int x,int y,int cap){    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;}inline void bfs(int t){    for (int i=1;i<=N;++i) deep[i]=N;    deep[t]=0;    for (int i=1;i<=N;++i) cur[i]=point[i];    while (!q.empty()) q.pop();    q.push(t);    while (!q.empty())    {        int now=q.front(); q.pop();        for (int i=point[now];i!=-1;i=nxt[i])            if (deep[v[i]]==N&&remain[i^1])            {                deep[v[i]]=deep[now]+1;                q.push(v[i]);            }    }}inline int addflow(int s,int t){    int ans=INF,now=t;    while (now!=s)    {        ans=min(ans,remain[last[now]]);        now=v[last[now]^1];    }    now=t;    while (now!=s)    {        remain[last[now]]-=ans;        remain[last[now]^1]+=ans;        now=v[last[now]^1];    }    return ans;}   inline void isap(int s,int t){    bfs(t);    for (int i=1;i<=N;++i) ++num[deep[i]];    int now=s;    while (deep[s]<N)    {        if (now==t)        {            maxflow+=addflow(s,t);            now=s;        }        bool has_find=false;        for (int i=cur[now];i!=-1;i=nxt[i])            if (deep[v[i]]+1==deep[now]&&remain[i])            {                has_find=true;                cur[now]=i;                last[v[i]]=i;                now=v[i];                    break;            }        if (!has_find)        {            int minn=N-1;            for (int i=point[now];i!=-1;i=nxt[i])                if (remain[i]) minn=min(minn,deep[v[i]]);            if (!(--num[deep[now]])) break;            num[deep[now]=minn+1]++;            cur[now]=point[now];            if (now!=s) now=v[last[now]^1];        }    }}int main(){    tot=-1;    memset(point,-1,sizeof(point));    memset(nxt,-1,sizeof(nxt));    scanf("%d%d%d",&n,&f,&d);    N=2*n+f+d+2;    for (int i=1;i<=f;++i)        addedge(1,1+i,1);    for (int i=1;i<=d;++i)        addedge(1+f+2*n+i,N,1);    for (int i=1;i<=n;++i)        addedge(1+f+i,1+f+n+i,1);    for (int i=1;i<=n;++i)    {        scanf("%d%d",&F,&D);        for (int j=1;j<=F;++j)        {            scanf("%d",&fi);            addedge(1+fi,1+f+i,1);        }        for (int j=1;j<=D;++j)        {            scanf("%d",&di);            addedge(1+f+n+i,1+f+2*n+di,1);        }    }    isap(1,N);    printf("%d\n",maxflow);}
0 0
原创粉丝点击