[网络流]poj1149 PIGS

来源:互联网 发布:怎么积累淘宝关注人数 编辑:程序博客网 时间:2024/05/19 00:14

题意:

一个农场有M个猪圈,每个猪圈里有很多猪,现在有N个顾客,每个顾客可以拿到一些猪圈的钥匙来买猪,买完之后会关上门,顾客是严格按照顺序来的,不会出现顾客A和顾客B同时在农场的情况。顾客打开门之后,这个猪圈里的猪可以任意换到其他的打开着的猪圈中,求最多能卖多少只猪。

思路:

这样的网络流题目,必然要构图。

从源点开始,向每个猪圈的第一个顾客连一条边,容量为这个猪圈的猪的数量。接着后面来的顾客由上一个到这个猪圈的顾客连接上,容量为∞

每一个顾客都连接一条弧到汇点,容量为他需要的猪的数量。

可以这样解释:

从源点开始,连接到每一个猪圈,容量为这个猪圈的猪的数量,再连接到第一个顾客,这时候,第一个顾客连两条边,一条连到汇点,另一条连到新开的一个节点,这个节点连接的就是后来来的顾客,这样重复,将部分路径压缩,也就是因为猪圈只会连到第一个顾客,就直接从源点连到第一个顾客。第一个顾客连完汇点之后,再连后来的顾客,这时候省略了中间作为中介的节点,而且查询起来也很快。

最后建好图,做一次最大流即可得到答案。

如图,这是原题根据样例构成的图:


总结:

网络流的题目,通常会出现很难连边或是很占用空间的情况,所以要想办法简化网络,从而达到更好的效果。

代码:

#include <queue>#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 1000 + 10,           INF = 0x3f3f3f3f,             s = 0,             t = 101;struct Edge {    int from, to, cap, flow;    Edge(int u, int v, int c, int f) : from(u), to(v), cap(c), flow(f) {}};struct EdmondsKarp {    int n, m;    vector < Edge > edges;    vector < int > G[MAXN];    int a[MAXN];    int p[MAXN];    void AddEdge(int from, int to, int cap) {        edges.push_back(Edge(from, to, cap, 0));        edges.push_back(Edge(to, from, 0, 0));        m = edges.size();        G[from].push_back(m - 2);        G[to].push_back(m - 1);    }    int Maxflow(int s, int t) {        int flow = 0;        for(;;) {            memset(a, 0, sizeof a);            queue < int > Q;            Q.push(s);            a[s] = INF;            while(!Q.empty()) {                int x = Q.front();                Q.pop();                for(int i = 0; i < G[x].size(); ++i) {                    Edge& e = edges[G[x][i]];                    if(!a[e.to] && e.cap > e.flow) {                        p[e.to] = G[x][i];                        a[e.to] = min(a[x], e.cap - e.flow);                        Q.push(e.to);                    }                }                if(a[t]) {                    break;                }            }            if(!a[t]) {                break;            }            for(int u = t; u != s; u = edges[p[u]].from) {                edges[p[u]].flow += a[t];                edges[p[u] ^ 1].flow -= a[t];            }            flow += a[t];        }        return flow;    }} ek;int main(void) {int m, n;cin >> m >> n;int N_pig[MAXN];int last_cus[MAXN];memset(last_cus, 0, sizeof last_cus);for(int i = 1; i <= m; ++i) {cin >> N_pig[i];}for(int i = 1; i <= n; ++i) {int N;cin >> N;for(int j = 0; j < N; ++j) {int can_visiting;cin >> can_visiting;if(last_cus[can_visiting] == 0) {ek.AddEdge(s, i, N_pig[can_visiting]);} else {ek.AddEdge(last_cus[can_visiting], i, INF);}last_cus[can_visiting] = i;}int wanted;cin >> wanted;ek.AddEdge(i, t, wanted);}cout << ek.Maxflow(s, t);    return 0;}

0 0
原创粉丝点击