题意:
给定一张有向图,每条边都有一个容量c和一个扩容费用w。这里扩容费用是指将容量扩大1所需的费用。
求: 在不扩容的情况下,1到n的最大流;将1到n的最大流增加k所需的最小扩容费用。
$nleq 1000,mleq 5000$。
题解:
先跑一边最大流,然后对每条边$(u,v,c,0)$再建一条$(u,v,inf,w)$的边。
源点限流为k,在残量网络上再跑一遍最小费用最大流即可。
复杂度$O(能过)$。
代码:
#include<bits/stdc++.h> #define maxn 1005 #define maxm 100005 #define inf 0x7fffffff #define ll long long #define rint register int #define debug(x) cerr<<#x<<": "<<x<<endl #define fgx cerr<<"--------------"<<endl #define dgx cerr<<"=============="<<endl using namespace std; int n,m,k,hd[maxn],to[maxm],fl[maxm],nxt[maxm],cnt; int dis[maxn],inq[maxn],cst[maxm],vis[maxn],cost; struct edge{int u,v,c,w;}E[maxm]; inline int read(){ int x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } inline void addedge(int u,int v,int w,int c){ to[++cnt]=v,fl[cnt]=w,cst[cnt]=c; nxt[cnt]=hd[u],hd[u]=cnt; } inline bool spfa(int ed){ queue<int> q; memset(dis,127,sizeof(dis)); memset(inq,0,sizeof(inq)); dis[1]=0,inq[1]=1,q.push(1); while(!q.empty()){ int u=q.front(); q.pop(),inq[u]=0; for(int i=hd[u];i;i=nxt[i]){ int v=to[i],w=fl[i],c=cst[i]; if(w>0 && dis[v]>dis[u]+c){ dis[v]=dis[u]+c; if(!inq[v]) q.push(v),inq[v]=1; } } } return dis[ed]<=2e9; } inline int dfs(int u,int flow,int ed){ if(u==ed) return flow; vis[u]=1; int sum=0; for(int i=hd[u];i;i=nxt[i]){ int v=to[i],w=fl[i],c=cst[i]; if(!vis[v] && w>0 && dis[v]==dis[u]+c){ int f=dfs(v,min(flow,w),ed); sum+=f,cost+=f*c; flow-=f,fl[i]-=f,fl[i^1]+=f; if(!flow) break; } } if(!sum) dis[u]=inf; return sum; } inline int Dinic(){ memset(hd,0,sizeof(hd)),cnt=1; for(int i=1;i<=m;i++){ addedge(E[i].u,E[i].v,E[i].c,0); addedge(E[i].v,E[i].u,0,0); } int ans=0; while(spfa(n)){ memset(vis,0,sizeof(vis)); ans+=dfs(1,inf,n); } return ans; } inline int MCMF(int res){ for(int i=1;i<=m;i++){ addedge(E[i].u,E[i].v,inf,E[i].w); addedge(E[i].v,E[i].u,0,-E[i].w); } addedge(n,n+1,k,0); int ans=0; while(spfa(n+1)){ memset(vis,0,sizeof(vis)); ans+=dfs(1,inf,n+1); } return cost; } int main(){ n=read(),m=read(),k=read(); for(int i=1;i<=m;i++) E[i].u=read(),E[i].v=read(),E[i].c=read(),E[i].w=read(); int res=Dinic(); printf("%d %d ",res,MCMF(res)); return 0; }