Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
Solution
第一问模板
第二问可以在第一问的残留网络上增加容量为INF费用为w的边,原本的边按照0费用处理,再从超级源点练到点1容量为k费用为0,这样就保证了费用尽可能小、只扩展k并且原本没有满流的边能被利用
Code
#include <stdio.h>
#include <string.h>
#include <queue>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define min(x,y) ((x)<(y)?(x):(y))
const int INF=0x3f3f3f3f;
const int N=50005;
const int E=400005;
struct edge{int x,y,w,c,next;}e[E];
std:: queue<int> que;
int dis[N],pre[N],c[N];
int ls[N],edCnt=1;
bool vis[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void addEdge(int x,int y,int w,int c) {
e[++edCnt]=(edge){x,y,w,c,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge){y,x,0,-c,ls[y]}; ls[y]=edCnt;
}
int bfs(int st,int ed) {
while (!que.empty()) que.pop();
que.push(st);
fill(dis,-1); dis[st]=1;
while (!que.empty()) {
int now=que.front(); que.pop();
for (int i=ls[now];i;i=e[i].next) {
if (e[i].w>0&&dis[e[i].y]==-1) {
que.push(e[i].y);
dis[e[i].y]=dis[now]+1;
if (e[i].y==ed) return 1;
}
}
}
return 0;
}
int find(int now,int ed,int mn) {
if (now==ed||!mn) return mn;
int ret=0;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].w>0&&dis[now]+1==dis[e[i].y]) {
int d=find(e[i].y,ed,min(mn-ret,e[i].w));
e[i].w-=d; e[i^1].w+=d; ret+=d;
if (ret==mn) break;
}
}
return ret;
}
int dinic(int st,int ed) {
int ret=0;
while (bfs(st,ed)) ret+=find(st,ed,INF);
return ret;
}
int spfa(int st,int ed) {
while (!que.empty()) que.pop();
que.push(st);
fill(vis,0); vis[st]=1;
fill(dis,31); dis[st]=0;
while (!que.empty()) {
int now=que.front(); que.pop();
for (int i=ls[now];i;i=e[i].next) {
if (e[i].w>0&&dis[now]+e[i].c<dis[e[i].y]) {
dis[e[i].y]=dis[now]+e[i].c;
pre[e[i].y]=i;
if (!vis[e[i].y]) {
que.push(e[i].y);
vis[e[i].y]=1;
}
}
}
vis[now]=0;
}
return dis[ed]!=dis[ed+1];
}
int modify(int ed) {
int mn=INF,cost=0;
for (int i=ed;pre[i];i=e[pre[i]].x) {
mn=min(e[pre[i]].w,mn);
cost+=e[pre[i]].c;
}
for (int i=ed;pre[i];i=e[pre[i]].x) {
e[pre[i]].w-=mn;
e[pre[i]^1].w+=mn;
}
return cost*mn;
}
int mcf(int st,int ed) {
int ret=0;
while (spfa(st,ed))
ret+=modify(ed);
return ret;
}
int main(void) {
int n=read(),m=read(),k=read();
rep(i,1,m) {
int x=read(),y=read(),w=read(); c[i]=read();
addEdge(x,y,w,0);
}
printf("%d\n", dinic(1,n));
rep(i,1,m) {
addEdge(e[i*2].x,e[i*2].y,INF,c[i]);
}
addEdge(0,1,k,0);
printf("%d\n", mcf(0,n));
return 0;
}