POJ 3281 最大流+建图
来源:互联网 发布:知错改错不认错的说说 编辑:程序博客网 时间:2024/06/08 20:16
题目大意:有n头牛,f种草料,d种水,每种草料和每种水仅有一个单位,每头牛要吃一个单位草料和喝一个单位水。每头牛只对一部分草料和一部分水感兴趣。问你最多能完全满足多少头牛(草料和水均满意)?
分析:经典构图题:用拆点来限制流量,超级源点与每种食物相连,负载为1。每头牛拆点,负载为1(此处限制流量,一头牛只能转移一的流量)。每头牛拆点的出点与所有满意的食物相连,负载为1;每头牛拆点的入点再与所有满意的水相连,负载为1,每种水再与超级汇点相连,负载为1。最终看最大流跑出多少就是最大的,能够双双满足的牛的数量。
图解:
(另外有一种变体是食物和饮料数量不是1,则相应改变超级源点和超级汇点连接的边为对应数量即可。)
上代码:
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<queue>
- #include<cstring>
- using namespace std;
-
- const int MAXM = 251000;
- const int MAXN = 510;
- const int INF = 0x3f3f3f3f;
-
- struct Edge
- {
- int to, cap, next;
- };
-
- Edge edge[MAXM];
- int level[MAXN];
- int head[MAXN];
- int src, des, cnt;
-
- void addedge( int from, int to, int cap )
- {
- edge[cnt].to = to;
- edge[cnt].cap = cap;
- edge[cnt].next = head[from];
- head[from] = cnt++;
-
- swap( from, to );
-
- edge[cnt].to = to;
- edge[cnt].cap = 0;
- edge[cnt].next = head[from];
- head[from] = cnt++;
- }
-
- int bfs()
- {
- memset( level, -1, sizeof level );
- queue<int>q;
- while (!q.empty())
- q.pop();
-
- level[src] = 0;
- q.push( src );
-
- while (!q.empty())
- {
- int u = q.front();
- q.pop();
-
- for (int i = head[u]; i != -1; i = edge[i].next)
- {
- int v = edge[i].to;
- if (edge[i].cap > 0 && level[v] == -1)
- {
- level[v] = level[u] + 1;
- q.push( v );
- }
- }
- }
- return level[des] != -1;
- }
-
- int dfs( int u, int f )
- {
- if (u == des) return f;
- int tem;
- for (int i = head[u]; i != -1; i = edge[i].next)
- {
- int v = edge[i].to;
- if (edge[i].cap>0&&level[v] == level[u] + 1)
- {
- tem = dfs( v, min( f, edge[i].cap ) );
- if (tem > 0)
- {
- edge[i].cap -= tem;
- edge[i^1].cap += tem;
- return tem;
- }
- }
- }
- level[u] = -1;
- return 0;
- }
-
-
- int Dinic()
- {
- int ans = 0, tem;
-
- while (bfs())
- {
- while ((tem = dfs( src, INF )) > 0)
- {
- ans += tem;
- }
- }
- return ans;
- }
-
-
-
- int main()
- {
- int n, f, d;
- src = 0;
- des = 505;
- while (cin >> n>>f>>d)
- {
- memset( head, -1, sizeof head );
- cnt = 0;
- for (int i = 1; i <= f; i++)
- addedge( src, i + 200, 1 );
- for (int i = 1; i <= d; i++)
- addedge( i + 300, des, 1 );
-
- for (int i = 1; i <= n; i++)
- {
- addedge( i, i + 100, 1 );
- int F, D;
- cin >> F>>D;
- for (int j = 1; j <= F; j++)
- {
- int tem;
- cin >> tem;
- addedge( tem + 200, i, 1 );
- }
- for (int j = 1; j <= D; j++)
- {
- int tem;
- cin >> tem;
- addedge( i+100, tem + 300, 1 );
- }
- }
- cout << Dinic() << endl;
- }
- return 0;
-
- }
0 0