zoj 3229 有源汇有上下界的最大流模板题

来源:互联网 发布:茶叶网络推广 编辑:程序博客网 时间:2024/04/30 12:19
/*坑啊,pe的程序在zoj上原来是wa。题目大意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝最多个C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能超过Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照;否则输出-1。解题思路:增设一源点st,汇点sd,st到第i天连一条上界为Di下界为0的边,每个女神到汇点连一条下界为Gi上界为oo的边,对于每一天,当天到第i个女孩连一条[Li,Ri]的边。建图模型:源点s,终点d。超级源点ss,超级终点dd。首先判断是否存在满足所有边上下界的可行流,方法可以转化成无源汇有上下界的可行流问题。怎么转换呢?增设一条从d到s没有下界容量为无穷的边,那么原图就变成了一个无源汇的循环流图。接下来的事情一样,超级源点ss连i(du[i]>0),i连超级汇点(du[i]<0),对(ss,dd)进行一次最大流,当maxflow等于所有(du[]>0)之和时,有可行流,否则没有。当有可行流时,删除超级源点ss和超级终点dd,再对(s,d)进行一次最大流,此时得到的maxflow则为题目的解。为什么呢?因为第一次maxflow()只是求得所有满足下界的流量,而残留网络(s,d)路上还有许多自由流(没有和超级源点和超级汇点连接的边)没有流满,所有最终得到的maxflow=(第一次流满下界的流+第二次能流通的自由流)。*/#include<stdio.h>#include<string.h>#include<queue>using namespace std;#define N  1500#define ii 400000#define inf 0x3fffffffstruct node {int u,v,w,f,next;}bian[ii*2];int head[N],yong,dis[N],work[N];void init(){yong=0;memset(head,-1,sizeof(head));}void addbian(int u,int v,int w,int f) {bian[yong].u=u;bian[yong].v=v;bian[yong].w=w;bian[yong].f=f;bian[yong].next=head[u];head[u]=yong++;}void add(int u,int v,int w,int f) {addbian(u,v,w,f);addbian(v,u,0,f);}int min(int a,int b){    return a<b?a:b;}int bfs(int s,int t){    memset(dis,-1,sizeof(dis));    queue<int>q;    q.push(s);    dis[s]=0;    while(!q.empty())    {        int u=q.front();        q.pop();        for(int i=head[u];i!=-1;i=bian[i].next)        {            int v=bian[i].v;            if(bian[i].w&&dis[v]==-1)            {                dis[v]=dis[u]+1;                q.push(v);                if(v==t)                    return 1;            }        }    }    return 0;}int dfs(int  s,int limit,int t){    if(s==t)return limit;    for(int &i=work[s];i!=-1;i=bian[i].next)    {        int v=bian[i].v;        if(bian[i].w&&dis[v]==dis[s]+1)        {            int tt=dfs(v,min(limit,bian[i].w),t);            if(tt)            {                bian[i].w-=tt;                bian[i^1].w+=tt;                return tt;            }        }    }    return 0;}int dinic(int s,int t){    int ans=0;    while(bfs(s,t))    {        memcpy(work,head,sizeof(head));        while(int tt=dfs(s,inf,t))            ans+=tt;    }    return ans;}int main() {   int n,m,i,j,k,s,t,S,T,a,b,d,index[ii],id,suma,w[N];   while(scanf("%d%d",&n,&m)!=EOF) {     init();    s=0;t=m+n+1;    S=t+1;T=S+1;    memset(w,0,sizeof(w));    for(i=1;i<=m;i++) {        scanf("%d",&a);          w[t]+=a;          w[i+n]-=a;          add(i+n,t,inf-a,0);    }    id=0;    for(i=1;i<=n;i++) {        scanf("%d%d",&a,&b);        add(s,i,b,b);        while(a--) {            scanf("%d%d%d",&j,&k,&d);            j++;            index[id++]=yong;            w[i]-=k;            w[j+n]+=k;            add(i,j+n,d-k,d);        }    }    add(t,s,inf,inf);    suma=0;    for(i=s;i<=t;i++) {        if(w[i]>0) {            suma+=w[i];            add(S,i,w[i],0);        }        else            add(i,T,-w[i],0);    }     int f=dinic(S,T);     if(f==suma) {            head[S]=head[T]=-1;        printf("%d\n",dinic(s,t));        for(i=0;i<id;i++)            printf("%d\n",bian[index[i]].f-bian[index[i]].w);     }     else        printf("-1\n");       printf("\n");   }return 0;}

0 0
原创粉丝点击