[ZJOI2010]网络扩容

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

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

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

Sample Input
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

Sample Output
13 19


费用流板子题吧……建费用为0,流量为C的边,和费用为W,流量为inf的边,直接跑费用流即可

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
template<typename T>T min(T x,T y){return x<y?x:y;}
template<typename T>T max(T x,T y){return x>y?x:y;}
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline T frd(T x){
	int f=1; char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
template<typename T>inline T read(T x){
	int f=1;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)    putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int N=1e3,M=2e4;
int pre[M+10],now[N+10],child[M+10],val[M+10],cost[M+10],tot=1;
int dis[N+10],deep[N+10],S,T;
void join(int x,int y,int v,int w){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=v,cost[tot]=w;}
void insert(int x,int y,int v,int w){join(x,y,v,w),join(y,x,0,-w);}
bool SPFA(){
	static int h[N+10];
	static bool vis[N+10];
	int head=0,tail=1;
	memset(dis,63,sizeof(dis));
	memset(deep,255,sizeof(deep));
	h[1]=S,dis[S]=0;
	while (head!=tail){
		if (++head>N)	head=1;
		int Now=h[head];
		for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
			if (val[p]&&dis[son]>dis[Now]+cost[p]){
				deep[son]=deep[Now]+1;
				dis[son]=dis[Now]+cost[p];
				if (!vis[son]){
					if (++tail>N)	tail=1;
					vis[h[tail]=son]=1;
				}
			}
		}
		vis[Now]=0;
	}
	return ~deep[T];
}
int Dinic(int x,int v){
	if (x==T)	return v;
	int res=0;
	for (int p=now[x],son=child[p];p;p=pre[p],son=child[p]){
		if (val[p]&&dis[son]==dis[x]+cost[p]&&deep[son]>deep[x]){
			int k=Dinic(son,min(v,val[p]));
			v-=k,val[p]-=k;
			res+=k,val[p^1]+=k;
			if (!v)	break;
		}
	}
	if (!res)	deep[x]=-1;
	return res;
}
void MCMF(int K){
	int MaxFlow=0,MinCost=0; bool put=0;
	while (SPFA()){
		if (dis[T]>0&&!put){
			printf("%d ",MaxFlow);
			put=1,MaxFlow=0;
		}
		int tmp=Dinic(S,inf);
		if (put&&K<=MaxFlow+tmp){
			MinCost+=(K-MaxFlow)*dis[T];
			printf("%d\n",MinCost);
			return;
		}
		MaxFlow+=tmp;
		MinCost+=tmp*dis[T];
	}
}
int main(){
	int n=read(0),m=read(0),K=read(0); S=1,T=n;
	for (int i=1;i<=m;i++){
		int x=read(0),y=read(0),v=read(0),w=read(0);
		insert(x,y,v,0);
		insert(x,y,inf,w);
	}
	MCMF(K);
	return 0;
}
posted @ 2019-03-30 21:13  Wolfycz  阅读(174)  评论(0编辑  收藏  举报