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;
}
原文地址:https://www.cnblogs.com/heyuhhh/p/10085472.html