您的位置:首页 > 理论基础 > 计算机网络

[bzoj1834][ZJOI2010]network 网络扩容

2017-06-23 08:08 274 查看

1834: [ZJOI2010]network 网络扩容

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 3194  Solved: 1654

[Submit][Status][Discuss]

Description

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

Input

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

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

30%的数据中,N<=100

100%的数据中,N<=1000,M<=5000,K<=10

HINT

Source

Day1

题解

分两问来做 第一问直接最大流没什么问题

关键是第二问 

在此时的残留网络上连边

建个超级源点 和1号点连一条容量为k的边 

(因为以前跑了一次最大流 这次只用跑k这个扩容量 以前的就不用重跑一遍 这样就相当于扩容了)

然后对于每个以前的边 重连一条容量inf 费用为给定费用的边 跑最小费用最大流即可 答案就是最小费用

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 0x7ffffff
using namespace std;
struct edge{int to,next,flow,cost,book;}e[1000001];
int d[1005],cnt=1,head[1005],flag[1005],from[1005];int n,m,k;int start,end,max_flow=0,min_cost=0;
void ini(int x,int y,int flow,int cost){e[++cnt].to=y;e[cnt].flow=flow;e[cnt].cost=cost;e[cnt].next=head[x];head[x]=cnt;}
void frini(int x,int y,int flow,int cost){e[++cnt].to=y;e[cnt].flow=flow;e[cnt].book=cost;e[cnt].next=head[x];head[x]=cnt;}
void insert(int x,int y,int flow,int cost){ini(x,y,flow,cost);ini(y,x,0,-cost);}
void frinsert(int x,int y,int flow,int cost){frini(x,y,flow,cost);frini(y,x,0,-cost);}
queue<int>q;
bool bfs(){
memset(d,-1,sizeof(d));
q.push(start);
d[start]=0;
while(!q.empty())
{
int k=q.front();q.pop();
for(int i=head[k];i;i=e[i].next){
int kk=e[i].to;
if(d[kk]==-1&&e[i].flow>0){
d[kk]=d[k]+1;
q.push(kk);
}
}
}
return d[end]!=-1;
}
int dfs(int x,int f){
if(x==end) return f;
int w,used=0;
for(int i=head[x];i;i=e[i].next){
int k=e[i].to;
if(d[k]==d[x]+1&&e[i].flow>0){
w=f-used;
w=dfs(k,min(w,e[i].flow));
e[i].flow-=w;e[i^1].flow+=w;
used+=w;
if(used==f) return f;
}
}
if(!used) d[x]=-1;
return used;
}
void dinic(){
while(bfs())
max_flow+=dfs(start,0x7ffffff);
}
bool spfa(){
memset(d,127,sizeof(d));
d[start]=0;q.push(start);flag[start]=1;
while(!q.empty()){
int k=q.front();q.pop();flag[k]=0;
for(int i=head[k];i;i=e[i].next){
int kk=e[i].to;
if(e[i].flow&&d[kk]>d[k]+e[i].cost){
d[kk]=d[k]+e[i].cost;from[kk]=i;
if(!flag[kk]){
flag[kk]=1;
q.push(kk);
}
}
}
}
return d[end]<inf;
}
void mcf(){
while(spfa()){
int mn=inf;
for(int i=from[end];i;i=from[e[i^1].to])
mn=min(mn,e[i].flow);
min_cost+=d[end]*mn;
for(int i=from[end];i;i=from[e[i^1].to])
{
e[i].flow-=mn;e[i^1].flow+=mn;
}
}
}
void rebuild(){
int tmp=cnt;
for(int i=2;i<=tmp;i+=2){
int x=e[i^1].to,y=e[i].to;
insert(x,y,inf,e[i].book);
}
insert(start,1,k,0);
}
int main(){
scanf("%d%d%d",&n,&m,&k);
int x,y,f,c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&f,&c);
frinsert(x,y,f,c);
}
start=1,end=n;
dinic();
printf("%d ",max_flow);
start=0;
rebuild();
mcf();
printf("%d",min_cost);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: