【最大流】POJ 1145 PIGS

来源:互联网 发布:办公网络 编辑:程序博客网 时间:2024/06/05 11:15

如果一时想不出很好的构图方法,不如先构造一个最直观,或者说最“硬来”的模型,然后再用合并结点和边的方法来简化这个模型。

经过简化以后,好的构图思路自然就会涌现出来了。

这是解决网络流问题的一个好方法。

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <string>#include <iostream>#include <algorithm>using namespace std;#include <queue>#include <stack>#include <vector>#include <deque>#include <set>#include <map>#define IN     freopen ("in.txt" , "r" , stdin);#define OUT  freopen ("out.txt" , "w" , stdout);typedef long long LL;const int MAXN = 111;//点数的最大值const int MAXM = 1111;//边数的最大值const LL INF = 1152921504;struct Edge{    int to,next,cap,flow;} edge[MAXM]; //注意是MAXMint tol;int head[MAXN];int gap[MAXN],dep[MAXN],cur[MAXN];void init(){    tol = 0;    memset(head,-1,sizeof (head));}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;    int i;    while(dep[start] < N)    {        if(u == end)        {            int Min = INF;            int inser;            for( 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( 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( 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( 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;}int flag[MAXM];int main(){    int n,m,a[MAXM],b,c;    while(scanf("%d%d",&m,&n)!=EOF)    {        init();        for(int i=1; i<=m; i++)            scanf("%d",&a[i]);        memset(flag,0,sizeof(flag));        for(int i=1; i<=n; i++)        {            int sum=0;            scanf("%d",&b);            for(int j=0; j<b; j++)            {                scanf("%d",&c);                if(flag[c]==0)                {                    flag[c]=i;                    sum+=a[c];                }                else                    addedge(flag[c],i,INF,0);            }            if(sum>0)                addedge(0,i,sum,0);            scanf("%d",&c);            addedge(i,n+1,c,0);        }        printf("%d\n",sap(0,n+1,n+2));    }    return 0;}


0 0
原创粉丝点击