poj 3281 Dining 最大流

题目链接:http://poj.org/problem?id=3281

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).

题目描述:有F种食物和D种饮料(1<=F<=100,1<=D<=100)、n头牛(1<=n<=100),每头牛有自己喜欢的一些食物和饮料。现在每头牛只能吃一种喜欢的食物和喝一种喜欢的饮料,一种食物和饮料也只能提供给一头牛。问最多能有多少头牛可以吃到食物喝到饮料。

算法分析:我们知道供应的资源不止一种,需求方只有牛这一个群体,所以我们可以把牛这一群体放在中间,两边是供应的资源,形成源点-食物-牛-饮料-汇点的有向边。 对每头牛 i 这个节点拆成 i 和 i+n 两个点,新增源点from和汇点to,源点到每一种食物连边,权值为1(因为每种食物只能提供给一头牛),每一种饮料到汇点连边,权值为1。接下来就是食物-牛-饮料的关系了:对牛喜欢的食物j连边 j->i ,喜欢的饮料k连边 i+n->k ,权值均为1。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<queue>
  8 #define inf 0x7fffffff
  9 using namespace std;
 10 const int maxn=1000+10;
 11 
 12 int n,F,D;
 13 struct node
 14 {
 15     int u,flow;
 16     int next;
 17 }edge[maxn*5];
 18 int head[maxn*5],edgenum;
 19 int from,to;
 20 int d[maxn*5];
 21 
 22 void add(int u,int v,int flow)
 23 {
 24     edge[edgenum].u=v ;edge[edgenum].flow=flow ;
 25     edge[edgenum].next=head[u];
 26     head[u]=edgenum++;
 27 
 28     edge[edgenum].u=u ;edge[edgenum].flow=0;
 29     edge[edgenum].next=head[v];
 30     head[v]=edgenum++;
 31 }
 32 
 33 int bfs()
 34 {
 35     memset(d,0,sizeof(d));
 36     d[from]=1;
 37     queue<int> Q;
 38     Q.push(from);
 39     while (!Q.empty())
 40     {
 41         int u=Q.front() ;Q.pop() ;
 42         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 43         {
 44             int v=edge[i].u;
 45             if (!d[v] && edge[i].flow>0)
 46             {
 47                 d[v]=d[u]+1;
 48                 Q.push(v);
 49                 if (v==to) return 1;
 50             }
 51         }
 52     }
 53     return 0;
 54 }
 55 
 56 int dfs(int u,int flow)
 57 {
 58     if (u==to || flow==0) return flow;
 59     int cap=flow;
 60     for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 61     {
 62         int v=edge[i].u;
 63         if (d[v]==d[u]+1 && edge[i].flow>0)
 64         {
 65             int x=dfs(v,min(cap,edge[i].flow));
 66             edge[i].flow -= x;
 67             edge[i^1 ].flow += x;
 68             cap -= x;
 69             if (cap==0) return flow;
 70         }
 71     }
 72     return flow-cap;
 73 }
 74 
 75 int dinic()
 76 {
 77     int sum=0;
 78     while (bfs()) sum += dfs(from,inf);
 79     return sum;
 80 }
 81 
 82 int main()
 83 {
 84     while (scanf("%d%d%d",&n,&F,&D)!=EOF)
 85     {
 86         memset(head,-1,sizeof(head));
 87         edgenum=0;
 88         from=2*n+F+D+1;
 89         to=from+1;
 90         int f,d,a;
 91         for (int i=2*n+1 ;i<=2*n+F ;i++)
 92             add(from,i,1);
 93         for (int i=2*n+F+1 ;i<=2*n+F+D ;i++)
 94             add(i,to,1);
 95         for (int i=1 ;i<=n ;i++)
 96         {
 97             scanf("%d%d",&f,&d);
 98             while (f--)
 99             {
100                 scanf("%d",&a);
101                 add(2*n+a,i,1);
102             }
103             while (d--)
104             {
105                 scanf("%d",&a);
106                 add(i+n,2*n+F+a,1);
107             }
108             add(i,i+n,1);
109         }
110         printf("%d
",dinic());
111     }
112     return 0;
113 }
原文地址:https://www.cnblogs.com/huangxf/p/4299878.html