首页 > 代码库 > [bzoj1834][ZJOI2010]network 网络扩容

[bzoj1834][ZJOI2010]network 网络扩容

来自FallDream的博客,未经允许,请勿转载,谢谢。


给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

n<=1000  m<=5000

第一问不说了,就是送分的。

然后假设求出了最大流W,那么我们重新构图,从S向1号点连流量为W+k,费用为0的边,其它边都建两条,一条流量为原流量,费用为0,另一条流量INF,费用是对应的费用,最后n向T连边就行了。

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define S 0#define T 1001#define INF 2000000000 using namespace std;inline int read(){    int x = 0 , f = 1; char ch = getchar();    while(ch < 0 || ch > 9){ if(ch == -) f = -1;  ch = getchar();}    while(ch >= 0 && ch <= 9){x = x * 10 + ch - 0;ch = getchar();}    return x * f;}struct edge{int to,next,w,c;}e[25005],E[25005]; int n,m,k,head[T+5],cnt=1,d[T+5],ans=0,pi=0,W;bool mark[T+5],inq[T+5];deque<int> q;inline void ins(int f,int t,int w,int c){    e[++cnt]=(edge){t,head[f],w,c}; head[f]=cnt;    e[++cnt]=(edge){f,head[t],0,-c};head[t]=cnt;}bool modlabel(){    for(int i=S;i<T;++i) d[i]=INF;    d[T]=0;q.push_back(T);inq[T]=1;    while(!q.empty())    {        int x=q.front();q.pop_front();        for(int i=head[x];i;i=e[i].next)            if(e[i^1].w&&d[x]+e[i^1].c<d[e[i].to])            {                d[e[i].to]=d[x]+e[i^1].c;                if(!inq[e[i].to])                {                    inq[e[i].to]=1;                    if(d[e[i].to]<d[q.size()?q.front():0])                         q.push_front(e[i].to);                    else q.push_back(e[i].to);                 }            }        inq[x]=0;    }    for(int i=S;i<=T;i++)        for(int j=head[i];j;j=e[j].next)            e[j].c+=d[e[j].to]-d[i];    return pi+=d[S],d[S]<INF;}int dfs(int x,int f){    if(x==T) return ans+=pi*f,f;    int used=0;mark[x]=1;    for(int i=head[x];i;i=e[i].next)        if(e[i].w&&!e[i].c&&!mark[e[i].to])         {            int w=dfs(e[i].to,min(f-used,e[i].w));            used+=w;e[i].w-=w;e[i^1].w+=w;            if(used==f) return f;        }    return used;}int main(){    n=read();m=read();k=read();        for(int i=1;i<=m;++i)    {        E[i].next=read();E[i].to=read();        E[i].w=read();E[i].c=read();        ins(E[i].next,E[i].to,E[i].w,0);    }    ins(S,1,INF,0);ins(n,T,INF,0);    while(modlabel())        do memset(mark,0,sizeof(mark));        while(W=dfs(S,INF),ans+=W,W);    printf("%d ",ans);    memset(head,0,sizeof(head));cnt=1;    ins(S,1,ans+k,0);ins(n,T,INF,0);    ans=0;pi=0;    for(int i=1;i<=m;++i)    {        ins(E[i].next,E[i].to,E[i].w,0);        ins(E[i].next,E[i].to,INF,E[i].c);    }     while(modlabel())        do memset(mark,0,sizeof(mark));        while(dfs(S,INF));    printf("%d",ans);    return 0;}

 

[bzoj1834][ZJOI2010]network 网络扩容