POJ3281 Dining(拆点构图 + 最大流)

题目链接

题意:有F种食物,D种饮料N头奶牛,只能吃某种食物和饮料(而且只能吃特定的一份)

一种食物被一头牛吃了之后,其余牛就不能吃了
第一行有N,F,D三个整数
接着2-N+1行代表第i头牛,前面两个整数是Fi与Di(食物与饮料的种类数量),接着是食物的种类与饮料的种类
要求输出最多分配能够满足的牛的数量

参考北理大神博客

分析:本想最大匹配搞,然后发现牛不仅要匹配食物还要匹配饮料。

最大流拆点构图, 食物 - 牛- 饮料,但是由于一个牛只能选择一个食物和一个饮料,也就是说牛这个节点有限制,最大就是1,然后把 牛这个节点拆成 牛 - 牛 其中之间流量是1,

于是 最后模型就是 食物 - 牛 - 牛 - 饮料  节点之间的流量都是1.

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <queue>
 5 #include <cstring>
 6 using namespace std;
 7 const int Max = 500;
 8 const int INF = 0x3f3f3f3f;
 9 int g[Max][Max];
10 int N, F, D;
11 int pre[Max];
12 int BFS()
13 {
14     memset(pre, -1, sizeof(pre));
15     int MinFlow = INF;
16     queue<int> que;
17     pre[0] = 0;
18     que.push(0);
19     int des = F + 2 * N + D + 1;
20     while (!que.empty())
21     {
22         int x = que.front();
23         que.pop();
24         if (x == des)
25             break;
26         for (int i = 1; i <= des; i++)
27         {
28             if (pre[i] == -1 && g[x][i])
29             {
30                 if (MinFlow > g[x][i])
31                 {
32                     MinFlow = g[x][i];
33                 }
34                 pre[i] = x;
35                 que.push(i);
36             }
37         }
38     }
39     if (pre[des] == -1)
40         return -1;
41     return MinFlow;
42 }
43 void EK()
44 {
45     int MaxFlow = 0, inFlow = 0, des;
46     while ( (inFlow = BFS()) != -1)
47     {
48         MaxFlow += inFlow;
49         des = F + 2 * N + D + 1;
50         while (des != 0)
51         {
52             g[des][pre[des]] += inFlow;
53             g[pre[des]][des] -= inFlow;
54             des = pre[des];
55         }
56     }
57     printf("%d\n", MaxFlow);
58 }
59 void buildGraph()
60 {
61     while (scanf("%d%d%d", &N, &F, &D) != EOF)
62     {
63         memset(g, 0, sizeof(g));
64         int fd, fnum, dnum;
65         for (int i = 1; i <= N; i++)
66         {
67             scanf("%d%d", &fnum, &dnum);
68             for (int j = 0; j < fnum; j++)
69             {
70                 scanf("%d", &fd);
71                 g[0][fd] = 1;  // 0点作为起点连接每个食物
72                 g[fd][F + i] = 1; // 食物和牛相连,食物最大F,
73             }
74             g[F + i][F + N + i] = 1; // 牛 和 牛相连 
75             for (int j = 1; j <= dnum; j++)
76             {
77                 scanf("%d", &fd);
78                 g[F + N + i][F + N + N + fd] = 1;  // 牛和饮料相连
79                 g[F + N + N + fd][F + N + N + D + 1] = 1; // 设一个终点让每一个 饮料 和他相连,流量为1
80             }
81         }
82         EK();
83     }
84 }
85 int main()
86 {
87     buildGraph();
88     return 0;
89 }
View Code

 

posted @ 2016-04-19 19:41  zhaop  阅读(174)  评论(0编辑  收藏  举报