POJ 1149 (网络流,有趣的建图)

来源:互联网 发布:广州医科大学知乎 编辑:程序博客网 时间:2024/05/01 10:18

网络流(建图是重点)

题意:

有一个卖猪的农夫,他有n个猪圈,但是猪圈的钥匙不在他的手上,有m个顾客,每一个顾客会带一些猪圈的钥匙,每一个顾客都有自己想买猪的数量,当然他所带的钥匙能开启相应的猪圈,从而能买到相应的猪,不过有时猪比他想买的数量多,也有可能少。而农夫有一个权力,就是如果某一个顾客没有买完他开的猪圈里的猪,农夫可以把剩下的猪随意的转移在被这个顾客的开启的猪圈里面。求出农夫最多能卖多少猪?

思路:

切入点应该是“转移”字眼吧,意味着可以用网络流解决问题,因为没有花费的存在,那么就是最大流。

我们知道网络流难点是在于把问题抽象成网络,进而建图。

因为我做的网络流不是很多,不过这道题教会了我一个方法去建图,先把所有条件列在纸上,在纸上试着根据题意建一个图,根据题意的意思是有很多限制条件而重点就是在限制条件上建图,然后手动跑一边网络流看看时都能得到结果。如果能得到,那么很可能就是对的建图。

这道题的建图方式就是:猪圈的猪的限制条件是顾客,我们把源点与猪圈连成边,猪圈和顾客连成边,因为猪圈可能会有多个顾客访问,我们只连最先访问的顾客,如果有多个顾客访问这个猪圈,就把剩下的顾客与第一次访问的顾客相连成边,流量是无限大,这意味着前边顾客买不完的猪可以让后边的顾客买。

最后每一个顾客与汇点连成边流量是顾客买猪的最大值。

  • 注意点:顾客与顾客之间建图的时候,注意重边,就是顾客与顾客之间最多建一次就行了。
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <vector>using namespace std;const int maxn = 2005;const int INF = 0x3f3f3f3f;struct edge{    int to,cap,rev;};int n,m;vector<edge>G[maxn];int pignum[maxn];int vis[maxn];int level[maxn],iter[maxn];void add_edge(int from,int to,int cap){    int length = G[from].size();    int length1 = G[to].size();    G[from].push_back((edge){to,cap,length1});    G[to].push_back((edge){from,0,length});}void bfs(int s){    memset(level,-1,sizeof(level));    queue<int>Q;    Q.push(s);    level[s] = 0;    while(!Q.empty()) {        int to = Q.front();        Q.pop();        int length = G[to].size();        for(int i = 0;i < length; i++) {            edge &e = G[to][i];            if(e.cap > 0 && level[e.to] < 0) {                level[e.to] = level[to] + 1;                Q.push(e.to);            }        }    }}int dfs(int u,int t,int f){    if(u == t) return f;    else {        int length = G[u].size();        for(int &i = iter[u];i < length; i++) {            edge &e = G[u][i];            if(e.cap > 0 && level[e.to] > level[u]) {                int d = dfs(e.to,t,min(f,e.cap));                if(d > 0) {                    e.cap -= d;                    G[e.to][e.rev].cap += d;                    return d;                }            }        }    }    return 0;}int max_flow(int s,int t){    int flow = 0;    for(;;) {        bfs(s);        if(level[t] < 0)            break;        memset(iter,0,sizeof(iter));        int f;        while((f = dfs(s,t,INF)) > 0) {            flow += f;        }    }    return flow;}int main(){    //freopen("in.txt","r",stdin);    scanf("%d%d",&n,&m);    for(int i = 1;i <= n; i++) {        scanf("%d",&pignum[i]);        add_edge(0,i,pignum[i]);    }    for(int i = n+1;i <= n+m; i++) {        int pighouse;        scanf("%d",&pighouse);        for(int k = 0;k < pighouse; k++) {            int pig;            scanf("%d",&pig);            if(vis[pig] == 0) {                vis[pig] = true;                add_edge(pig,i,pignum[pig]);            }            else {                int uppeople = G[pig][1].to;                int length = G[uppeople].size();                int flag = true;                for(int j = 0;j < length; j++) {                    if(G[uppeople][j].to == i) {                        flag = false;                        break;                    }                }                if(flag) {                    add_edge(uppeople,i,INF);                }            }        }        int sum;        scanf("%d",&sum);        add_edge(i,n+m+1,sum);    }    printf("%d\n",max_flow(0,n+m+1));    return 0;}
原创粉丝点击