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

输入格式
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。

输出格式
输出文件一行包含两个整数,分别表示问题1和问题2的答案。

输入输出样例
输入 #1 复制

5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
输出 #1 复制
13 19
说明/提示
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10


对于第一问直接最大流即可,费用加为0即可。

第二问我们利用第一问的残量网络,在往里面加边,和最大流加的边一样,只不过流量变为k,费用变为题目给出的值,同时我们要保证流量不会超过k,所以我们连一条n到n+1流量为k,费用为0的边,跑1到n+1的费用流即可。


AC代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
int n,m,k,s,t,a[N],b[N],c[N],d[N],v[N],e[N],dst[N];
int head[N],nex[N],to[N],w[N],flow[N],tot=1;
inline void ade(int a,int b,int c,int d){
	to[++tot]=b; w[tot]=d; flow[tot]=c; nex[tot]=head[a]; head[a]=tot;
}
inline void add(int a,int b,int c,int d){
	ade(a,b,c,d);	ade(b,a,0,-d);
}
int bfs(){
	queue<int> q;	int vis[N]={0};	q.push(s);	vis[s]=1;
	while(q.size()){
		int u=q.front();	q.pop();
		for(int i=head[u];i;i=nex[i]){
			if(flow[i]&&!vis[to[i]]){
				vis[to[i]]=1;	q.push(to[i]);
				v[to[i]]=u;	e[to[i]]=i;
				if(to[i]==t)	return 1;
			}
		}
	}
	return 0;
}
int spfa(){
	memset(dst,inf,sizeof dst);	queue<int> q;	q.push(s);	dst[s]=0;
	int vis[N]={0};	vis[s]=1;
	while(q.size()){
		int u=q.front();	q.pop();	vis[u]=0;
		for(int i=head[u];i;i=nex[i]){
			if(flow[i]&&dst[to[i]]>dst[u]+w[i]){
				dst[to[i]]=dst[u]+w[i];
				v[to[i]]=u;	e[to[i]]=i;
				if(!vis[to[i]])	q.push(to[i]),vis[to[i]]=1;
			}
		}
	}
	return dst[t]!=inf;
}
int EK(int k){
	int res=0;
	while((k?spfa():bfs())){
		int mi=inf;
		for(int i=t;i!=s;i=v[i])	mi=min(mi,flow[e[i]]);
		for(int i=t;i!=s;i=v[i])	flow[e[i]]-=mi,flow[e[i]^1]+=mi;
		if(k)	res+=mi*dst[t];	else	res+=mi;
	}
	return res;
}
signed main(){
	cin>>n>>m>>k;	s=1;	t=n;
	for(int i=1;i<=m;i++){
		cin>>a[i]>>b[i]>>c[i]>>d[i];	add(a[i],b[i],c[i],0);
	}
	cout<<EK(0)<<' ';
	for(int i=1;i<=m;i++)	add(a[i],b[i],k,d[i]);
	t=n+1;
	add(n,t,k,0);
	cout<<EK(1)<<endl;
	return 0;
}