poj1149 PIGS DINIC

来源:互联网 发布:seo招聘北京 编辑:程序博客网 时间:2024/04/30 18:47

题意: 有 M 个猪圈,每个猪圈里初始时有若干头猪。一开始所有猪圈都是关闭的。依次来了 N 个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪。每个顾客分别都有他能够买的数量的上限。每个顾客走后,他打开的那些猪圈中的猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上。

分析: 此题是网络流,网络流里经典的构图题。将顾客看作除源和汇以外的节点,源和每个猪圈的第一个顾客连边,边的权是开始时猪圈中猪的数目,若源和某个节点之间有重边,则将权合并,每个猪圈的前后相邻两顾客之间连边,由前一个顾客指向后一个顾客。每个顾客和汇之间连边,边的权是顾客所希望购买的猪的数目。

网络流,需要对图进行化简

化简规则:

规律 1. 如果几个节点的流量的来源完全相同,则可以把它们合并成一个。
规律 2. 如果几个节点的流量的去向完全相同,则可以把它们合并成一个。
规律 3. 如果从点 u 到点 v 有一条容量为 +∞ 的边,并且 u 是 v 的唯一流量来源,或者 v 是 u 的唯一流量去向,则可以把 u 和 v 合并成一个节点。

#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <queue>#include <vector>#include <cmath>using namespace std;#define maxn 20000#define INF   0x7fffffffint n,m;int en;int st,ed;  //源点和汇点int dis[maxn] ;//dis[i],表示  到 原点  s 的 层数int que[9999999];int cur[maxn];struct node{    int pig,last;};node house[9999999];int head[maxn];int save[110][110];int bfs(){    memset(dis,-1,sizeof(dis));    dis[st]=0;    int h=0,tail=0;    tail++;    que[tail]=st;    while(h<tail)    {        h++;        int j=que[h];        for(int i=0;i<=ed;i++)        {            if(save[j][i]<=0) continue;            if(dis[i]==-1&&save[j][i])            {                dis[i] = dis[j]+ 1 ;                tail++;                que[tail]=i;                if(i==ed) return true;            }        }    }    return false;}int dfs(int x,int mx){    if(x==ed||mx==0) return mx;    int f,flow=0;    for(int i=0;i<=ed;i++)    {        if(save[x][i]<=0) continue;        if(dis[x]+1==dis[i]&&(f=dfs(i,min(mx,save[x][i]) )))        {            save[x][i]-=f;            save[i][x]+=f;            flow+=f;            mx-=f;            if(!mx)break;        }    }    return flow;}int dinic(){    int tmp=0;    int maxflow=0;    while(bfs())    {        while(tmp=dfs(st,INF)) maxflow+=tmp;    }    return maxflow;}void init(){    en=0;    st=0;     //源    ed=n+1;     //汇    memset(head,-1,sizeof(head));    memset(save,0,sizeof(save));}void build(){    int key,open,cust;    for(int i=1;i<=m;i++)    {        scanf("%d",&house[i].pig);        house[i].last=0;    }    for(int i=1;i<=n;i++)    {        scanf("%d",&key);        for(int j=0;j<key;j++)        {            scanf("%d",&open);            if(!house[open].last)            {                save[st][i]+=house[open].pig;                house[open].last=i;            }            else            {                save[house[open].last][i]=INF;                house[open].last=i;            }        }        scanf("%d",&cust);        save[i][ed]=cust;    }}int main(){    while(scanf("%d%d",&m,&n)!=EOF)    {        init();        build();        printf("%d\n",dinic());    }    return 0;}


0 0