题目描述
给定一张有向图,每条边都有一个容量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
思路
有点暴力。先跑一遍dinic,求出第一问的解,再重新建图,讲扩容记为容量inf,费用的边,最后新建t点,容量为maxflow+k,跑最大流最小费用,即可得到ans。
代码
#include<bits/stdc++.h>
#define N 10700
#define M 107000
#define inf 1<<29
using namespace std;
struct node{
int x,y,z,p,next;
}e[M*2];
int tot=1,head[N],maxflow=0,ans=0;
int x[M],y[M],z[M],cost[M];
int n,m,s,t,K;
void add(int x,int y,int z,int p){
e[++tot].y=y;e[tot].z=z;e[tot].p=p;e[tot].next=head[x];head[x]=tot;
e[++tot].y=x;e[tot].z=0;e[tot].p=-p;e[tot].next=head[y];head[y]=tot;
}
int incf[N],v[N],pre[N],d[N];
queue<int> q;
bool bfs(){
memset(d,0,sizeof(d));
while(q.size()) q.pop();
q.push(s);d[s]=1;
while(q.size()){
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].next){
int y=e[i].y,z=e[i].z;
if(z&&!d[y]){
q.push(y);d[y]=d[x]+1;
if(y==t) return 1;
}
}
}
return 0;
}
int dinic(int x,int flow){
if(x==t) return flow;
int rest=flow,k;
for(int i=head[x];i;i=e[i].next){
int y=e[i].y,z=e[i].z;
if(z&&d[y]==d[x]+1){
k=dinic(y,min(rest,z));
if(!k) d[y]=0;
e[i].z-=k;
e[i^1].z+=k;
rest-=k;
}
}
return flow-rest;
}
bool spfa(){
queue<int> q;
memset(d,0x3f,sizeof(d));// 0xcf
memset(v,0,sizeof(v));
q.push(s);d[s]=0;v[s]=1;
incf[s]=inf;
while(q.size()){
int x=q.front();v[x]=0;q.pop();
for(int i=head[x];i;i=e[i].next){
int y=e[i].y,z=e[i].z;
if(!z) continue;
if(d[y]>d[x]+e[i].p){//d[y]<d[x]+e[i].p
d[y]=d[x]+e[i].p;
incf[y]=min(incf[x],z);
pre[y]=i;
if(!v[y]) v[y]=1,q.push(y);
}
}
}
if(d[t]==0x3f3f3f3f) return false;//0xcfcfcfcf
return true;
}
void update(){
int x=t;
while(x!=s){
int i=pre[x];
e[i].z-=incf[t];
e[i^1].z+=incf[t];
x=e[i^1].y;
}
maxflow+=incf[t];
ans+=d[t]*incf[t];
}
void rebuild(){
s=1;t=n+1;
memset(head,0,sizeof(head));tot=1;
for(int i=1;i<=m;i++){
add(x[i],y[i],z[i],0);
add(x[i],y[i],inf,cost[i]);
}
add(n,n+1,maxflow+K,0);
}
int main()
{
int flow=0;
cin>>n>>m>>K;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&x[i],&y[i],&z[i],&cost[i]);
add(x[i],y[i],z[i],0);
} s=1;t=n;
while(bfs())
while(flow=dinic(s,inf)) maxflow+=flow;
cout<<maxflow<<" ";
rebuild();
while(spfa()) update();
cout<<ans<<endl;
return 0;
}