好久没有给自己的博客添加博文了。。
poj3281是一道网络流的题目,也是我写的第二道网络流。参考了别人的代码过了
题意:一个农场主要喂养他的牛, 就给它们做了好多好吃好喝的。但是牛很挑剔,每头牛都只吃特定的食物和喝特定的饮料。问农场主最多能满足多少头牛。
解题思路:这就是个网络流的题目,关键是构图。重点在于将牛分成两个点存。最开始我也不是很理解,后来就明白了。牛的左半边和右半边中间有一条权为1的边,就保证了一头牛只能享用一份食物和饮料。
源码:
//#define LOCAL
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define MAXN 500
#define INF 0x7fffffff
int n, f, d;
int map[MAXN][MAXN];
int flow[MAXN][MAXN];
int minflow[MAXN];
int pre[MAXN];
void getmap()
{
int i, j;
int a, b;
int food, drink;
memset(map, 0, sizeof(map));
for(i = 1; i <= f; i++) // super src
map[0][i] = 1;
for(i = 1; i <= d; i++) // super dest
map[f + 2* n + i][f + 2 * n + d + 1] = 1;
for(i = 1; i <= n; i++)
{
scanf("%d%d", &a, &b);
for(j = 1; j <= a; j++) // food -> cow(left)
{
scanf("%d", &food);
map[food][f + i] = 1;
}
map[f + i][f + n + i] = 1; cow(left) --> cow(right)
for(j = 1; j <= b; j++) // cow(right) --> drink
{
scanf("%d", &drink);
map[f + n + i][f + 2 * n + drink] = 1;
}
}
}
int maxflow()
{
int s, t, cur, u, v, ans = 0;
s = 0; // src
t = f + 2 * n + d + 1; // dest
memset(flow, 0, sizeof(flow));
while(1)
{
memset(pre, -1, sizeof(pre));
memset(minflow, 0, sizeof(minflow));
queue<int> q;
minflow[s] = INF;
q.push(s);
while(!q.empty())
{
cur = q.front();
q.pop();
if(cur == t)
break;
for(v = s; v <= t; v++)
{
if(pre[v] < 0 && map[cur][v] > flow[cur][v])
{
pre[v] = cur;
minflow[v] = min(map[cur][v] - flow[cur][v], minflow[cur]);
q.push(v);
}
}
}
if(pre[t] == -1)
break;
for(v = t; v != s; v = pre[v])
{
u = pre[v];
flow[u][v] += minflow[v];
flow[v][u] -= minflow[v];
}
ans += minflow[t];
}
return ans;
}
int main()
{
#ifdef LOCAL
freopen("poj3281.txt", "r", stdin);
// freopen(".txt", “w”, stdin);
#endif
while(scanf("%d%d%d", &n, &f, &d) != EOF)
{
getmap();
printf("%d\n", maxflow());
}
return 0;
}
感觉现在我写这种类型的题目思路都比较清晰了,以后自己写的题就会放上详细的题解了,(图文并茂)。