poj-3281(拆点+最大流)

题意:有n头牛,f种食物,d种饮料,每头牛有自己喜欢的食物和饮料,问你最多能够几头牛搭配好,每种食物或者饮料只能一头牛享用;

解题思路:把牛拆点,因为流过牛的流量是由限制的,只能为1,然后,食物和牛的入点相连,牛的出点和饮料相连,求解最大流

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=200500;
const int inf=0x3f3f3f3f;
struct Edge
{
    int fa;
    int next;
    int to;
    int w;
}edge[maxn];
int n,m,f,d;
int head[maxn];
int cnt,Start,End;
int x,y,w;
int depth[maxn];
void add(int u,int v,int w)
{
    //cout<<u<<" "<<v<<endl;
    edge[cnt].next=head[u];edge[cnt].fa=u;
    edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt++;
    edge[cnt].next=head[v];edge[cnt].fa=v;
    edge[cnt].to=u;edge[cnt].w=0;head[v]=cnt++;
}
bool bfs()//分层;
{
    memset(depth,0,sizeof(depth));
    queue<int>q;
    q.push(Start);
    depth[Start]=1;
    while(!q.empty())
    {
        int temp=q.front();
        q.pop();
        for(int i=head[temp];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(depth[v]||edge[i].w<=0)
                continue;
            depth[v]=depth[temp]+1;
            q.push(v);
        }
    }
    return depth[End];//若为0表示没法到达也就是没有路径了;
}
int dfs(int u,int maxflow)
{
    if(u==End)
        return maxflow;
    int add=0;
    for(int i=head[u];i!=-1&&add<maxflow;i=edge[i].next)
    {
        int v=edge[i].to;
        if(depth[v]!=depth[u]+1)
            continue;
        if(edge[i].w==0)
            continue;
        int tempflow=dfs(v,min(edge[i].w,maxflow-add));
        edge[i].w-=tempflow;
        edge[i^1].w+=tempflow;
        add+=tempflow;
    }
    return add;
}
int dinic()
{
    int ans=0;
    while(bfs())
    {
        ans+=dfs(Start,0x3f3f3f3f);
    }
    return ans;
}
int main()
{
    int tmp;
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&f,&d);
    Start=0;End=2*n+f+d+1;
    for(int i=1;i<=n;i++)
        add(i,i+n,1);
    for(int i=2*n+1;i<=2*n+f;i++)
        add(Start,i,1);
    for(int i=2*n+f+1;i<=2*n+f+d;i++)
        add(i,End,1);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        for(int j=1;j<=x;j++)
        {
            scanf("%d",&tmp);
            add(tmp+2*n,i,1);
        }
        for(int j=1;j<=y;j++)
        {
            scanf("%d",&tmp);
            add(i+n,tmp+2*n+f,1);
        }
    }
    int ans=dinic();
    printf("%d\n",ans);
}

  

posted @ 2018-11-15 20:28  荒岛的龟  阅读(201)  评论(0编辑  收藏  举报