题目链接:http://poj.org/problem?id=1149
Description
Input
Output
Sample Input
3 3 3 1 10 2 1 2 2 2 1 3 3 1 2 6
Sample Output
7
Source
代码如下:
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <iostream> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define MAXN 500047 #define MAXM 1247 int head[MAXM], pre[MAXM]; int dep[MAXM], cur[MAXM], gap[MAXM]; int EN; int con[MAXM][MAXM];//记录商人与猪栏之间是否相连 struct Edge { int to,next,cap,flow; } edge[MAXN]; //注意是MAXM int tol; int k, c, m; int s, e;//源点,汇点 int map[MAXM][MAXM]; //加边,单向图三个参数,双向图四个参数 void addedge(int u,int v,int w,int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; void BFS(int start,int end) { memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while(front != rear) { int u = Q[front++]; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; //输入参数:起点、终点、点的总数 //点的编号没有影响,只要输入点的总数 int sap(int start,int end,int N) { BFS(start,end); memcpy(cur,head,sizeof(head)); int top = 0; int u = start; int ans = 0; while(dep[start] < N) { if(u == end) { int Min = INF; int inser; for(int i = 0; i < top; i++) if(Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for(int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i]^1].flow -= Min; } ans += Min; top = inser; u = edge[S[top]^1].to; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = i; break; } } if(flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if(u != start)u = edge[S[--top]^1].to; } return ans; } void init() { memset(head,-1,sizeof(head)); memset(con,0,sizeof(con)); EN = 0; } int main() { int m, n; while(~scanf("%d%d",&m,&n)) { init(); int num; for(int i = 1; i <= m; i++) { scanf("%d",&num); addedge(0, i, num);//源点 } int a, b, c[MAXM]; for(int i = 1; i <= n; i++) { scanf("%d",&a); for(int j = 1; j <= a; j++) { scanf("%d",&c[j]); addedge(c[j], m+i, INF);//猪和商人 con[i][c[j]] = 1;//第i个商人能买的 } scanf("%d",&b);//能买几头 addedge(m+i, m+n+1, b);//商人和汇点 } for(int i = 1; i < n; i++)//商人与商人之间,从前到后 { int vis[MAXM];//记录是否已经加过边 memset(vis,0,sizeof(vis)); for(int j = 1; j <= m; j++) { if (con[i][j])//如果商人能买 { for(int k = i+1; k <= n; k++) { if (con[k][j] && !vis[k])//判断商人k和猪栏j是否相连 { addedge(m+i, m+k, INF); vis[k] = 1; } } } } } int sta = 0;//起点 int end = m+n+1;//汇点 int N = m+n+2;//总结点数 int ans = sap(sta,end,N); printf("%d\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u012860063/article/details/46957175