给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
输出格式:
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
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
13 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
第一问是裸的最大流,直接 Dinic。
第二问在第一问的残流网络上继续建图:对于数据中的m条边,再次建为容量INF,费用W[I]的边,最后再把0和1之间建上一条容量为k的边,用 SPFAMCMF 求0到n的最小费用流即可。
注:n应该<=5000
附代码:
#include
#include
#include
#include
#include
#define MAXN 5010
#define MAX 999999999
using namespace std;
int n,m,s,t,c=2,k,mincost=0;
int head[MAXN],path[MAXN],flow[MAXN],fa[MAXN],deep[MAXN];
bool vis[MAXN];
struct node1{
int next,to,w,cost;
}a[MAXN<<2];
struct node2{
int u,v,w,cost;
}b[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
void add(int u,int v,int w,int cost){
a[c].to=v;a[c].w=w;a[c].cost=cost;
a[c].next=head[u];
head[u]=c++;
a[c].to=u;a[c].w=0;a[c].cost=-cost;
a[c].next=head[v];
head[v]=c++;
}
bool bfs(){
int u,v;
queue q;
memset(deep,0,sizeof(deep));
deep[s]=1;
q.push(s);
while(!q.empty()){
u=q.front();
q.pop();
for(int i=head[u];i;i=a[i].next){
v=a[i].to;
if(a[i].w&&!deep[v]){
deep[v]=deep[u]+1;
if(v==t)return true;
q.push(v);
}
}
}
return false;
}
int dfs(int x,int limit){
if(x==t)return limit;
int v,sum,cost=0;
for(int i=head[x];i;i=a[i].next){
v=a[i].to;
if(a[i].w&&deep[v]==deep[x]+1){
sum=dfs(v,min(limit-cost,a[i].w));
if(sum>0){
a[i].w-=sum;
a[i^1].w+=sum;
cost+=sum;
if(limit==cost)break;
}
else deep[v]=-1;
}
}
return cost;
}
int dinic(){
int ans=0;
while(bfs())
ans+=dfs(s,MAX);
return ans;
}
bool spfa(){
int u,v;
queue q;
for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;fa[i]=-1;deep[i]=0;}
path[s]=0;
vis[s]=true;
fa[s]=0;
flow[s]=MAX;
q.push(s);
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i;i=a[i].next){
v=a[i].to;
if(a[i].w&&path[v]>path[u]+a[i].cost){
path[v]=path[u]+a[i].cost;
deep[v]=i;
fa[v]=u;
flow[v]=min(flow[u],a[i].w);
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
if(path[t]!=MAX)return true;
return false;
}
void EK(){
while(spfa()){
for(int i=t;i!=s;i=fa[i]){
a[deep[i]].w-=flow[t];
a[deep[i]^1].w+=flow[t];
}
mincost+=flow[t]*path[t];
}
}
int main(){
n=read();m=read();k=read();
s=1;t=n;
for(int i=1;i<=m;i++){
b[i].u=read();b[i].v=read();b[i].w=read();b[i].cost=read();
add(b[i].u,b[i].v,b[i].w,0);
}
printf("%d ",dinic());
s=0;
for(int i=1;i<=m;i++)add(b[i].u,b[i].v,MAX,b[i].cost);
add(0,1,k,0);
EK();
printf("%d\n",mincost);
return 0;
}