Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
Input
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
Output
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
HINT
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
网络流与费用流二合一233~
首先第一问显然没有什么好讲的,直接跑一遍最大流即可。
接下来是第二问。既然$k$这么小,那么我们保留下跑最大流后的残量网络,显然残量网络中有流量的边都是有可以直接流的,并且不需要任何费用。
然后我们对于原图中的每一条边,新建一条容量为$inf$,费用为扩容费用 的边。接下来新建一个源点,向$1$号点连一条容量为$k$,费用为$0$的边,控制一下流量。
最后跑一遍最小费用最大流即可。
下面贴代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define maxn 1010 #define maxm 20010 #define INF (1<<25) using namespace std; typedef long long llg; struct data{ int u,v,c,w; }s[maxm]; int n,m,K,d[maxn],dep[maxn],ans,S,fa[maxn]; int head[maxn],next[maxm],to[maxm],c[maxm],f[maxm],tt=1; bool w[maxn]; int getint(){ int w=0;bool q=0; char c=getchar(); while((c>'9'||c<'0')&&c!='-') c=getchar(); if(c=='-') c=getchar(),q=1; while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } bool bfs(){ int l=0,r=0; for(int i=1;i<=n;i++) dep[i]=-1; dep[1]=1; d[r++]=1; while(l!=r){ int u=d[l++]; for(int i=head[u],v;v=to[i],i;i=next[i]) if(c[i] && dep[v]==-1) dep[v]=dep[u]+1,d[r++]=v; } return dep[n]!=-1; } int dfs(int u,int now){ if(u==n) return now; if(!now) return 0; int low=0; for(int i=head[u],v,res;v=to[i],i;i=next[i]) if(c[i] && dep[v]==dep[u]+1){ res=dfs(v,min(now,c[i])); low+=res; c[i]-=res; c[i^1]+=res; now-=res; } if(!low) dep[u]=-1; return low; } bool spfa(){ int l=0,r=0; for(int i=1;i<=n;i++) dep[i]=-1,w[i]=0; dep[S]=0; d[r++]=S; w[S]=1; while(l!=r){ int u=d[l++]; w[u]=0; if(l==maxn) l=0; for(int i=head[u],v;v=to[i],i;i=next[i]) if(c[i] && (dep[v]==-1 || dep[v]>dep[u]+f[i])){ dep[v]=dep[u]+f[i]; fa[v]=i; if(!w[v]){ d[r++]=v; w[v]=1; if(r==maxn) r=0; } } } return dep[n]!=-1; } int get(){ int now=INF,ans=0; for(int u=n;u!=S;u=to[fa[u]^1]) now=min(now,c[fa[u]]),ans+=f[fa[u]]; for(int u=n;u!=S;u=to[fa[u]^1]) c[fa[u]]-=now,c[fa[u]^1]+=now; return now*ans; } int main(){ File("a"); n=getint(); m=getint(); K=getint(); for(int i=1,u,v;i<=m;i++){ s[i].u=getint(),s[i].v=getint(); s[i].c=getint(),s[i].w=getint(); u=s[i].u; v=s[i].v; to[++tt]=v;next[tt]=head[u];head[u]=tt; to[++tt]=u;next[tt]=head[v];head[v]=tt; c[tt-1]=s[i].c; } while(bfs()) ans+=dfs(1,INF); printf("%d",ans); for(int i=1,u,v;i<=m;i++){ u=s[i].u,v=s[i].v; to[++tt]=v;next[tt]=head[u];head[u]=tt; to[++tt]=u;next[tt]=head[v];head[v]=tt; c[tt-1]=INF; f[tt-1]=s[i].w; f[tt]=-s[i].w; } S=n+1; ans=0; to[++tt]=1;next[tt]=head[S];head[S]=tt; c[tt]=K; to[++tt]=S;next[tt]=head[1];head[1]=tt; while(spfa()) ans+=get(); printf(" %d",ans); return 0; }