[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; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream