Poj1149 PIGS (经典网络流)

来源:互联网 发布:网络编程 博客园 编辑:程序博客网 时间:2024/05/22 00:47

顾客买猪问题


建图的方法:

当第i个猪圈第顾客K(不是每一个顾客都去打开每一个猪圈)一次被打开的时候, 就从超级源点连一条到顾客K的边, 权值为猪圈i里面猪的数量

当第i个猪圈不是是第一次被打开的时候, 那么就将上一个打开这个猪圈的人连到当前顾客, 权值为正无穷

将所有顾客都连一一条边倒超级汇点, 权值是顾客想买猪的数量


//SPA#include <cstring>#include <cstdio>#include <queue>#include <algorithm>#define CLR(arr, val) memset(arr, val, sizeof(arr))#pragma warning(disable:4996)using namespace std;const int MaxV = 1003;const int MaxE = 10000 << 1;const int INF = 1e9;struct Graph{struct Vertex{int head;}V[MaxV];struct Edge {int v, c, f, next;Edge(){}Edge(int v,int c, int f, int next):v(v), c(c), f(f), next(next){}}E[MaxE];void init(){top = 0;CLR(V, -1);}void addEdge(int u, int v,int w){E[top] = Edge(v, w, 0, V[u].head);V[u].head = top++;E[top] = Edge(u, 0, 0, V[v].head);V[v].head = top++;}int top;};int h[MaxV];        //高度int path[MaxV];     //回路int gap[MaxV];      //gap优化int cur[MaxV];      //当前弧优化int s, t;int vexNum, edgeNum;Graph g;void setHeight(){CLR(gap, 0);CLR(h, -1);h[t] = 0;queue<int>Q;Q.push(t);while(!Q.empty()){int top = Q.front();gap[ h[top] ]++;for(int i = g.V[top].head; i != -1; i = g.E[i].next){int v = g.E[i].v;if(h[v] == -1){h[v] = h[top] + 1;Q.push(v);}}Q.pop();}}int sap(){setHeight();int maxFlow = 0, u = s;int flow = INF;for(int i = 0; i <= vexNum; i++)cur[i] = g.V[i].head;while(h[s] < vexNum){int &i = cur[u];for(; i != -1; i = g.E[i].next){int v = g.E[i].v;if(g.E[i].c > g.E[i].f && h[u] == h[v] + 1){u = v;path[v] = i;flow = min(flow, g.E[i].c - g.E[i].f);if(u == t){while(u != s){int j = path[u];g.E[j].f += flow;g.E[j ^ 1].f -= flow;u = g.E[j ^ 1].v;}maxFlow += flow;flow = INF;}break;}}if(i == -1){if(--gap[ h[u] ] == 0)break;int minH = vexNum - 1;cur[u] = g.V[u].head;for(int j = g.V[u].head; j != -1; j = g.E[j].next)if(g.E[j].c > g.E[j].f)minH = min(minH, h[g.E[j].v]);h[u] = minH + 1;++gap[ h[u] ];if(u != s)u = g.E[path[u] ^ 1].v;}}return maxFlow;}int N, M;int pagNum[1003]; //1000个猪圈, 猪圈里面猪的数量int lastOpen[1003];   //1000个猪圈, lastopen[i] 是最后打开猪圈i的顾客int main(){while(scanf("%d %d", &M, &N) != EOF){g.init();CLR(lastOpen, -1);s = 0, t = N + 1;vexNum = N + 2;for(int i = 1; i <= M; i++)scanf("%d", &pagNum[i]);for(int i = 1; i <= N; i++){int A;scanf("%d", &A);while(A--){int v;scanf("%d", &v);if(lastOpen[v] == -1) //第一次被打开{g.addEdge(s, i, pagNum[v]);lastOpen[v] = i;}else{g.addEdge(lastOpen[v], i, INF);lastOpen[v] = i;}}int B;scanf("%d", &B);g.addEdge(i, t, B);}printf("%d\n", sap());}return 0;}/*2 22 22 1 2 11 2 10*/


原创粉丝点击