1. 程式人生 > >POJ3281:Dining(最大流)

POJ3281:Dining(最大流)

Dining

 

題目連結https://vjudge.net/problem/POJ-3281

Description:

Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.

Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although he might not be able to stuff everybody, he wants to give a complete meal of both food and drink to as many cows as possible.

Farmer John has cooked F (1 ≤ F ≤ 100) types of foods and prepared D (1 ≤ D ≤ 100) types of drinks. Each of his N (1 ≤ N ≤ 100) cows has decided whether she is willing to eat a particular food or drink a particular drink. Farmer John must assign a food type and a drink type to each cow to maximize the number of cows who get both.

Each dish or drink can only be consumed by one cow (i.e., once food type 2 is assigned to a cow, no other cow can be assigned food type 2).

Input:

Line 1: Three space-separated integers: NF, and D 
Lines 2.. N+1: Each line i starts with a two integers Fi and Di

, the number of dishes that cow i likes and the number of drinks that cow i likes. The next Fi integers denote the dishes that cow i will eat, and theDi integers following that denote the drinks that cow i will drink.

Output:

Line 1: A single integer that is the maximum number of cows that can be fed both food and drink that conform to their wishes

Sample Input:

4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3

Sample Output:

3

題意:

有n只奶牛,每隻奶牛都有其喜歡的幾種食物和飲料,但每種食物和飲料只能用一次,問最多可以滿足多少隻奶牛(可以同時提供喜歡的食物和飲料)

題解:

這個建圖很巧妙,如果只考慮食物或者飲料,那麼就是二分圖匹配。

在這裡,我們把牛拆點,左邊的牛連線食物,右邊的牛連線飲料,然後對應的牛連線起來,邊權都為1,這樣就可以保證每頭牛隻能提供一種食物和一種飲料。

然後跑個最大流就可以了。

我一開始想的是對於每一個食物和飲料的二元組都有其對應的牛,然後這樣來建圖。

但不知道哪裡一直WA...我想的是可能我二元組這裡處理地有點問題,我是用食物和飲料值的和來代表二元組的。這樣邏輯上或多或少可能會出現點問題吧。

 

程式碼如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#define INF 99999999
using namespace std;
const int N = 105,M = 100005,P = 1005;
int n,F,D;
int head[P+5],d[P+5],tot;
struct Edge{
    int v,next,c;
}e[M];
void adde(int u,int v,int w){
    e[tot].v=v;e[tot].c=w;e[tot].next=head[u];head[u]=tot++;
    e[tot].v=u;e[tot].c=0;e[tot].next=head[v];head[v]=tot++;
}
bool bfs(int S,int T){
    memset(d,0,sizeof(d));d[S]=1;
    queue <int > q;q.push(S);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(!d[v] && e[i].c>0){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[T]!=0;
}
int dfs(int s,int a){
    int flow=0,f;
    if(s==P || a==0) return a;
    for(int i=head[s];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(d[v]!=d[s]+1) continue ;
        f=dfs(v,min(a,e[i].c));
        if(f){
            e[i].c-=f;
            e[i^1].c+=f;
            flow+=f;
            a-=f;
            if(a==0) break;
        }
    }
    if(!flow) d[s]=-1;
    return flow;
}
int Dinic(){
    int max_flow=0;
    while(bfs(0,P))
        max_flow+=dfs(0,INF);
    return max_flow;
}
int main(){
    scanf("%d%d%d",&n,&F,&D);
    memset(head,-1,sizeof(head));
    for(int i=1;i<=F;i++) adde(0,i,1);
    for(int i=F+1;i<=F+D;i++) adde(i,P,1);
    for(int i=1,k1,k2;i<=n;i++){
        adde(300+i,400+i,1);
        scanf("%d%d",&k1,&k2);
        for(int j=1,c;j<=k1;j++){
            scanf("%d",&c);
            adde(c,300+i,1);
        }
        for(int j=1,c;j<=k2;j++){
            scanf("%d",&c);
            adde(400+i,F+c,1);
        }
    }
    printf("%d",Dinic());
    return 0;
}