网络流建图(典型)(EK)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Let_life_stop/article/details/83113563

题目链接:https://cn.vjudge.net/contest/68128#problem/B

具体思路:

按照  源点 - > 食物 - > 牛1 - > 牛2 - > 饮料 的方式建图。 求最大流就相当于求最大匹配量。

AC代码;

#include<iostream>
#include<string>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<stdio.h>
#include<queue>
using namespace std;
# define maxn 2000+10
# define inf 0x3f3f3f3f
# define ll long long
int Map[maxn][maxn];
int vis[maxn];
int pre[maxn];
bool bfs(int st,int ed)
{
    memset(vis,0,sizeof(vis));
    vis[st]=1;
    pre[st]=st;
    queue<int>q;
    q.push(st);
    while(!q.empty())
    {
        int top=q.front();
        q.pop();
        for(int i=1; i<=ed; i++)
        {
            if(Map[top][i]&&!vis[i])
            {
                vis[i]=1;
                pre[i]=top;
                if(i==ed)return true;
                q.push(i);
            }
        }
    }
    return false;
}
int EK(int st,int ed)
{
    int ans=0;
    while(bfs(st,ed))
    {
        int minn=inf;
        for(int i=ed; i!=st; i=pre[i])
        {
            minn=min(minn,Map[pre[i]][i]);
        }
        for(int i=ed; i!=st; i=pre[i])
        {
            Map[pre[i]][i]-=minn;
            Map[i][pre[i]]+=minn;
        }
        ans+=minn;
    }
    return ans;
}
int main()
{
    int n,f,d;
    while(~scanf("%d%d%d",&n,&f,&d))
    {
        memset(Map,0,sizeof(Map));
        int t1,t2,temp;
        int divn=n+f+d;
        int start=n+divn+1;
        int ed=start+1;
        for(int i=1; i<=n; i++)
        {
            scanf("%d%d",&t1,&t2);
            for(int j=1; j<=t1; j++)
            {
                scanf("%d",&temp);
                
                Map[temp][f+d+i]=1;//食物到牛1
            }
            for(int j=1; j<=t2; j++)
            {
                scanf("%d",&temp);
                Map[divn+i][f+temp]=1;//牛2到饮料
            }
        }
        for(int i=1; i<=n; i++)
        {
            Map[f+d+i][divn+i]=1;//牛1与牛2 建立关系
        }
        for(int i=1; i<=f; i++)
        {
            Map[start][i]=1;//源点与牛1建立关系
        }
        for(int i=1; i<=d; i++)
        {
            Map[f+i][ed]=1;//饮料与汇点建立关系
        }
        int ans=EK(start,ed);
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Let_life_stop/article/details/83113563