POJ 3281 网络流 拆点 Dining

题意:

有F种食物和D种饮料,每头牛有各自喜欢的食物和饮料,而且每种食物或者饮料只能给一头牛。

求最多能有多少头牛能同时得到它喜欢的食物或者饮料。

分析:

把每个牛拆点,中间连一条容量为1的边,保证一头牛不会被多个食物或者饮料分配。

然后把饮料和牛连边,食物和另外一边的牛连边,最后增加一个源点和汇点跑最大流。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <queue>
  7 using namespace std;
  8
  9 const int maxn = 100 + 10;
 10 const int maxnode = 400 + 10;
 11 const int INF = 0x3f3f3f3f;
 12
 13 int N, F, D;
 14
 15 int n, s, t;
 16
 17 struct Edge
 18 {
 19     int from, to, cap, flow;
 20     Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
 21 };
 22
 23 vector<Edge> edges;
 24 vector<int> G[maxnode];
 25
 26 void init()
 27 {
 28     edges.clear();
 29     for(int i = 0; i < n; i++) G[i].clear();
 30 }
 31
 32 void AddEdge(int u, int v, int c)
 33 {
 34     edges.push_back(Edge(u, v, c, 0));
 35     edges.push_back(Edge(v, u, 0, 0));
 36     int m = edges.size();
 37     G[u].push_back(m - 2);
 38     G[v].push_back(m - 1);
 39 }
 40
 41 bool vis[maxnode];
 42 int d[maxnode];
 43 int cur[maxnode];
 44
 45 bool BFS()
 46 {
 47     d[s] = 0;
 48     queue<int> Q;
 49     Q.push(s);
 50     memset(vis, false, sizeof(vis));
 51     vis[s] = true;
 52
 53     while(!Q.empty())
 54     {
 55         int u = Q.front(); Q.pop();
 56         for(int i = 0; i < G[u].size(); i++)
 57         {
 58             Edge& e = edges[G[u][i]];
 59             int v = e.to;
 60             if(!vis[v] && e.cap > e.flow)
 61             {
 62                 vis[v] = true;
 63                 d[v] = d[u] + 1;
 64                 Q.push(v);
 65             }
 66         }
 67     }
 68
 69     return vis[t];
 70 }
 71
 72 int DFS(int u, int a)
 73 {
 74     if(u == t || a == 0) return a;
 75     int flow = 0, f;
 76     for(int& i = cur[u]; i < G[u].size(); i++)
 77     {
 78         Edge& e = edges[G[u][i]];
 79         int v = e.to;
 80         if(d[v] == d[u] + 1 && (f = DFS(v, min(a, e.cap - e.flow))) > 0)
 81         {
 82             flow += f;
 83             e.flow += f;
 84             a -= f;
 85             edges[G[u][i]^1].flow -= f;
 86             if(a == 0) break;
 87         }
 88     }
 89     return flow;
 90 }
 91
 92 int Maxflow()
 93 {
 94     int flow = 0;
 95     while(BFS())
 96     {
 97         memset(cur, 0, sizeof(cur));
 98         flow += DFS(s, INF);
 99     }
100     return flow;
101 }
102
103 int main()
104 {
105     while(scanf("%d%d%d", &N, &F, &D) == 3)
106     {
107         n = N * 2 + D + F + 2;
108         s = 0, t = n - 1;
109         init();
110
111         //build graph
112         for(int i = 1; i <= F; i++) AddEdge(s, N*2+i, 1);
113         for(int i = 1; i <= D; i++) AddEdge(N*2+F+i, t, 1);
114         for(int i = 1; i <= N; i++) AddEdge(i, i + N, 1);
115
116         for(int i = 1; i <= N; i++)
117         {
118             int f, d, x; scanf("%d%d", &f, &d);
119             while(f--)
120             {
121                 scanf("%d", &x);
122                 AddEdge(N*2+x, i, 1);
123             }
124             while(d--)
125             {
126                 scanf("%d", &x);
127                 AddEdge(N + i, N*2+F+x, 1);
128             }
129         }
130
131         printf("%d\n", Maxflow());
132     }
133
134     return 0;
135 }

代码君

时间: 2024-10-08 05:11:32

POJ 3281 网络流 拆点 Dining的相关文章

POJ 3281 网络流 拆点保证本身只匹配一对食物和饮料

如何建图? 最开始的问题就是,怎么表示一只牛有了食物和饮料呢? 后来发现可以先将食物与牛匹配,牛再去和饮料匹配,实际上这就构成了三个层次. 起点到食物层边的容量是1,食物层到奶牛层容量是1,奶牛层到饮料层容量是1,饮料层到终点容量是1. 但是后来发现有一组hack数据: 2 3 3 3 3 1 2 3 1 2 3 3 3 1 2 3 1 2 3 我们发现一头奶牛居然吃了多个套餐,所以要解决这个只需要将自己与自己建立一条容量是1的边就行了. #include <cstdio> #include

POJ 3281 网络流dinic算法

B - Dining Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3281 Appoint description: Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she wil

B - Dining POJ - 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

POJ 3281【拆点 &amp;&amp; 最大流经典建图】

Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11097   Accepted: 5096 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 fabulo

POJ 3281 网络流(dinic邻接矩阵、单路增广、多路增广)

思路:刚开始看题就想到怎么建图了,源点连向所有的食物,食物连牛,牛连饮料,饮料连汇点,所有的流量都是1.不过这样建图好后,WA了.原来是一头牛只能单一匹配一组食物和饮料,所以牛得拆点,牛之间得相连,流量为1,以保证单一匹配食物和饮料. 邻接矩阵dinic单路的代码: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #in

ACM Computer Factory POJ - 3436 网络流拆点+路径还原

每台电脑有p个组成部分,有n个工厂加工电脑. 每个工厂对于进入工厂的半成品的每个组成部分都有要求,由p个数字描述,0代表这个部分不能有,1代表这个部分必须有,2代表这个部分的有无无所谓. 每个工厂的产出也不尽相同,也是由p个数字代表,0代表这个部分不存在,1代表这个部分存在.每个工厂都有一个最大加工量. 给出这n个工厂的数据,求出最多能加工出多少台电脑 对于容量有限制,因此拆点 开始的机器没有零件,连接符合要求的点 最终的机器应该是完整的,把符合要求的点连接到汇点 因为已经拆过点限制了流量,所以

POJ 3281 Dining(最大流建图 &amp;&amp; ISAP &amp;&amp; 拆点)

题目链接:http://poj.org/problem?id=3281 努力练建图ing!!! 题意:有 N 头牛,有 F 种食物和 D 种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料. 第2行-第N+1行.是牛i 喜欢A种食物,B种饮料,及食物种类列表和饮料种类列表. 问最多能使几头牛同时享用到自己喜欢的食物和饮料.->最大流. 本题难点是建图: 思路:一般都是左边一个集合表示源点与供应相连,右边一个集合表示需求与汇点相连. 但是本题,牛作为需求仍然是一个群体,但是供

POJ 3281 Dining(网络最大流)

http://poj.org/problem?id=3281 Dining Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9121   Accepted: 4199 Description Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.

poj 3281 Dining(最大流)

poj 3281 Dining 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 prefer