Detailed poj3281 Dining (maximum flow)

Problem Description

Cattle are very picky eaters. Each cow will prefer certain foods and drinks, the other she did not eat.
Farmer John made delicious meals for his cattle, but he forgot to check the menu according to their preferences. Although he may not be able to fill all of them, but he wanted to give as many cows provide a complete meal food and drink.
Farmer John cook F (1≤F≤100) kinds of food, prepared D (1≤D≤100) kinds of drinks. Per cow (1≤N≤100) he had decided she was eating a particular food or drink certain beverages. Farmer John must assign each cow a food and a drink, so that cows get both at the same time maximize the number of food and beverage.
Each dish can only eat or drink from the cow (that is, once the type of food 2 is assigned to a cow, the cow can not be assigned to other types of food 2).

Entry

Line 1: Three space-separated integers: N, F and D
lines 2 .N + 1:. Each row of two integers i start Fi and Di, are the numbers of my favorite dishes and my favorite drink number. Fi next integer I want to eat the dishes of cattle, Di integer representation behind drink cow me to drink.

Export

Line 1: A single integer, it is possible to feed cows food and beverages in line with the wishes of the maximum number of cows at the same time

analysis:

Each cow to cow split into two
to establish a
source -> Food -> Cattle -> Cattle -> Beverages -> sink (the same two cows)
FIG, 1 are the right side
maximum flow is the greatest number of matches

Why is the "food -> cow -> cow -> drink" instead of "Food -> cow -> drink" it?
Because if it is
"Food -> cow -> drink"

then this will happen:
Here Insert Picture Description
the meaning is no guarantee that a cow select only one food and drink

And if it is " food -> cow -> cow -> drinks ", then:
Here Insert Picture Description
(painting really bad)
due to road traffic restrictions black arrow pointing to the middle, so you can ensure that only a select only one cow food and drink

General Plan is almost like this:
Here Insert Picture Description

code (EK algorithm):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<algorithm>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=1e3+5;;
int g[maxm][maxm];
int n,f,d;
int mark[maxm];
int pre[maxm];
int all;
int bfs(int s,int t){
    memset(mark,0,sizeof mark);
    memset(pre,0,sizeof pre);
    queue<int>q;
    q.push(s);
    mark[s]=1;
    pre[s]=s;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=0;i<=all;i++){
            if(!mark[i]&&g[x][i]){
                pre[i]=x;
                if(i==t)return 1;
                mark[i]=1;
                q.push(i);
            }
        }
    }
    return 0;
}
int ek(int s,int t){
    int ans=0;
    while(bfs(s,t)){
        int d=inf;
        for(int i=t;i!=s;i=pre[i]){//找最小detla
            d=min(d,g[pre[i]][i]);
        }
        for(int i=t;i!=s;i=pre[i]){
            g[pre[i]][i]-=d;//正边减小
            g[i][pre[i]]+=d;//反边增加
        }
        ans+=d;
    }
    return ans;
}
int main(){
    while(cin>>n>>f>>d){
        all=f+n+n+d+1;//总点数
        memset(g,0,sizeof g);
        for(int i=1;i<=f;i++){//食物是1-f
            g[0][i]=1;//源点和食物建边
        }
        for(int i=1;i<=n;i++){//牛是(f+1)-(f+n)  和(f+n+1)-(f+n+n);
            int k1,k2;
            cin>>k1>>k2;
            while(k1--){
                int t;
                cin>>t;
                g[t][f+i]=1;//食物和牛建边
            }
            g[f+i][f+n+i]=1;//牛和自己建边
            while(k2--){//饮料是 (f+n+n+1)-(f+n+n+d)
                int t;
                cin>>t;
                g[f+n+i][f+n+n+t]=1;//牛和饮料建边
            }
        }
        for(int i=f+n+n+1;i<=f+n+n+d;i++){//和汇点建边
            g[i][all]=1;
        }
        cout<<ek(0,all)<<endl;
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_44178736/article/details/95023869