POJ1149最大流
2013-07-30 22:12 凝月流风 阅读(231) 评论(0) 编辑 收藏 举报
难度在于建图,剩下的就是求最大流问题了。
贴上我的实现代码
//题目的难度在于如何建图,将每一个客户当做点,另外添加一个源点s和汇点t,每个客户点建一条有向边指向汇点t,容量为该客户要购买的猪的数量; //若客户i是猪圈j的第一个访问者,则从源点s建一条边指向节点i,容量为猪圈的初始猪数,若客户i不是猪圈j的第一个客户,而该猪圈的上一个客户(pre数组记录)是 //x,那么从x建一条边指向i, 容量为正无穷,支持建图完成,剩下只需算出s到t的最大流即可,以下用EK算法实现; #include <stdio.h> #include <string.h> #include <queue> using namespace std; const int MAXN = 1001; const int N = 101; const int MAX = 0x7FFFFFFF; int c[N][N], path[N], pre[MAXN], flow[N]; //pre数组记录某猪圈的前一个访问者,建图需要 queue<int>Q; int Edmonds_Karp(int s, int t) { int sum = 0; int u, v; while (1) { memset(path, -1, sizeof(path)); while (!Q.empty()) Q.pop(); flow[s] = MAX; Q.push(s); while (!Q.empty() && path[t] == -1) { u = Q.front(); Q.pop(); for (v = 0; v <= t; v++) { if (c[u][v] && path[v] == -1) { path[v] = u; flow[v] = flow[u] < c[u][v] ? flow[u] : c[u][v]; Q.push(v); } } } if (path[t] != -1) { sum += flow[t]; v = t; while (v != s) { c[path[v]][v] -= flow[t]; c[v][path[v]] += flow[t]; v = path[v]; } } else { break; } } return sum; } int main() { int n1, k, order, i, j, n, m; int val[MAXN]; while (scanf("%d%d", &m, &n) != EOF) { memset(c, 0, sizeof(c)); memset(pre, 0, sizeof(pre)); //以下为读取数据并建图 for (i = 1; i <= m; i++) scanf("%d", &val[i]); for (i = 1; i <= n; i++) { scanf("%d", &n1); for (j = 0; j < n1; j++) { scanf("%d", &order); if (!pre[order]) { c[0][i] += val[order]; }else { c[pre[order]][i] = MAX; } pre[order] = i; } scanf("%d", &k); c[i][n+1] = k; } //求最大流 int sum = Edmonds_Karp(0, n+1); printf ("%d\n", sum); } return 0; }