[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;
}