poj 1149 PIGS【网络流经典建图】

来源:互联网 发布:python跨文件全局变量 编辑:程序博客网 时间:2024/05/16 06:15

题目链接;

题意:
有n个顾客,有m个猪圈,每个猪圈有一定的猪,在开始的时候猪圈都是关闭的,顾客来买猪,顾客打开某个猪圈,可以在其中挑选一定的猪的数量,在这个顾客走后,可以在打开的猪圈中将某个猪圈的一些猪牵到另外一个打开的猪圈,然后所有的猪圈会关闭,这样下一个顾客来了继续上面的工作。

第一行是两个整数:m和n(1≤M≤1000,1≤N≤100)
m是猪圈的数目,n是顾客的数目
第二行是m个整数,为每个猪圈中初始猪的数目,范围是[0,1000]
第三行接下来有N行,每行第一个数A代表第几个顾客会依次打开A个猪圈,然后跟着有A个数,代表顾客打开的是哪个猪圈.最后有一个数代表这个顾客可以买多少只猪
现在求怎么一种方法,使所有顾客买的猪的总数最大.

思路:
源点 -》 顾客 -》 汇点 。(源点为0,顾客编号为1~n,汇点为n + 1)
第一步:
源点与顾客之间: 能够第一次进入i号猪圈的顾客与源点相连,流量为i号猪圈的猪数量。
第二步:
顾客与顾客之间:进入i号猪圈的第p位与第p + 1位连接,流量为无限大(因为与原点相连的那条流量做出了限制),随意支配猪的流动。
第三步:
顾客与汇点之间:每位顾客都可以与汇点相连,流量为该顾客需要的猪数量。

建图的题目类型;

#include <cstdio>  #include <cstring>   #include <queue>  #include <vector>#include <algorithm>  #define MAXN 2000+50#define INF 0x3f3f3fusing namespace std;int dist[MAXN], cur[MAXN], head[MAXN];int pig[MAXN], need[MAXN], vis[MAXN];int top;vector<int> G[MAXN];struct Edge {    int to, cap, flow, next;}edge[MAXN * 200];void addedge(int a, int b, int c) {//  int i; //处理重边,可以不用 //  for(i = head[a]; i != -1; i = edge[i].next) {//      if(edge[i].to == b) break;//  }//  if(i != -1) {//      if(c != INF) edge[i].cap += c;//      return;//  }    Edge E1 = {b, c, 0, head[a]};    edge[top] = E1;    head[a] = top++;    Edge E2 = {a, 0, 0, head[b]};    edge[top] = E2;    head[b] = top++;}bool BFS(int start, int end) {     memset(dist, -1, sizeof(dist));      memset(vis, 0, sizeof(vis));      queue<int> Q;     Q.push(start);    vis[start] = 1;    dist[start] = 0;     while(!Q.empty()) {        int u = Q.front();        Q.pop();        for(int i = head[u]; i != -1; i = edge[i].next) {            Edge E = edge[i];            if(!vis[E.to] && E.cap > E.flow) {                dist[E.to] = dist[u] + 1;                vis[E.to] = 1;                if(E.to == end) return true;                Q.push(E.to);            }        }    }    return false;}int DFS(int x, int cost, int end) {     if(x == end || cost == 0) return cost;    int flow = 0, f;    for(int& i = cur[x]; i != -1; i = edge[i].next) {        Edge& E = edge[i];        if(dist[E.to] == dist[x] + 1 &&  (f = DFS(E.to, min(cost, E.cap - E.flow), end)) > 0) {             E.flow += f;            edge[i ^ 1].flow -= f;            flow += f;            cost -= f;            if(cost == 0) break;        }    }    return flow;}int Maxflow(int start, int end) {    int flow = 0;    while(BFS(start, end)) {         memcpy(cur, head, sizeof(head));        flow += DFS(start, INF, end);    }    return flow;}int t, k, n, m;void getmap() { //核心部分     for(int i = 1; i <= m; i++) {        scanf("%d", &pig[i]);    }    for(int i = 1; i <= n; i++) {        scanf("%d", &t);        while(t--) {            scanf("%d", &k);            G[k].push_back(i); //猪圈和顾客相连接         }        scanf("%d", &need[i]); //顾客需要的猪     }    for(int i = 1; i <= m; i++) {        int u = G[i][0]; //和源点链接         addedge(0, u, pig[i]);        for(int j = 0; j < G[i].size() - 1; j++) { //别忘了减一             int x = G[i][j];            int y = G[i][j + 1];            addedge(x, y, INF);  //前后来到i号猪圈的顾客之间流无限大         }    }    for(int i = 1; i <= n; i++) {        addedge(i, n + 1, need[i]);    }}int main() {    while(scanf("%d %d", &m, &n) != EOF) {        top = 0;        memset(head, -1, sizeof(head));        memset(edge, 0, sizeof(edge));        memset(G, 0, sizeof(G));        getmap();        printf("%d\n", Maxflow(0, n + 1));    }    return 0;} 
原创粉丝点击