POJ 3281 网络流

题意:
这里写图片描述
这里写图片描述
思路:
网络流 重在建图…

建完了图 就一切都好说了

这道题 我的想法是 先把源点和所有的食品连上边 (容量为1)

再把食品和对应的奶牛连上边 (容量为1)

这个时候要拆点 因为每只奶牛只能才吃1种东西嘛

就把奶牛拆成两个点

两个点之间连上一条容量为1的边

把奶牛分裂的第二个点 连到对应的饮料上

最后所有饮料向汇点连一条容量为1的边就好啦

大功告成~~~

//By SiriusRen
#include <queue> 
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100050
int n,f,d,ans,xx,w[N],v[N],first[555],tot,next[N],vis[N],yy,jy;
void add(int x,int y,int z){
    w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;
}
bool tell(){
    queue<int>q;
    q.push(0);
    memset(vis,-1,sizeof(vis));
    vis[0]=0;
    while(!q.empty()){
        int t=q.front();q.pop();
        for(int i=first[t];~i;i=next[i]){
            if(w[i]&&vis[v[i]]==-1){
                q.push(v[i]);
                vis[v[i]]=vis[t]+1;
            }
        }
    }
    return vis[501]!=-1;
}
int zeng(int x,int y){
    if(x==501)return y;
    int r=0;
    for(int i=first[x];y>r&&~i;i=next[i]){
        if(w[i]&&vis[v[i]]==vis[x]+1){
            int t=zeng(v[i],min(y-r,w[i]));
            w[i]-=t,w[i^1]+=t,r+=t;
        }
    }
    if(!r)vis[x]=-1;
    return r;
}
void flow(){
    while(tell())while(xx=zeng(0,0x3fffffff))ans+=xx;
    printf("%d\n",ans);
}
int main()
{
    memset(first,-1,sizeof(first));
    scanf("%d%d%d",&n,&f,&d);
    for(int i=1;i<=f;i++)add(0,i,1),add(i,0,0); 
    for(int i=1;i<=n;i++){
        add(100+i,200+i,1);
        add(200+i,100+i,0);
        scanf("%d%d",&xx,&yy);
        for(int j=1;j<=xx;j++){
            scanf("%d",&jy);
            add(jy,100+i,1);
            add(100+i,jy,0);
        }
        for(int j=1;j<=yy;j++){
            scanf("%d",&jy);
            add(200+i,300+jy,1);
            add(300+jy,200+i,0);
        }
    }
    for(int i=1;i<=d;i++)add(300+i,501,1),add(501,300+i,0);
    flow();
}

这里写图片描述

posted @ 2016-10-10 23:02  SiriusRen  阅读(112)  评论(0编辑  收藏  举报