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

【BZOJ 1834】 [ZJOI2010]network 网络扩容

2015-04-19 09:01 337 查看

1834: [ZJOI2010]network 网络扩容

Time Limit: 3 Sec Memory Limit: 64 MB

Submit: 1891 Solved: 937

[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

最大流+费用流

第一问是最大流模板;

第二问:我们在第一问的残量网络中建立费用流模型,从s到1连流量为k,费用为0的边,并对原图中的每一条边再连上费用为wiw_i流量为inf的边,然后跑费用流即可。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <cstdio>
#define M 1005
#define inf 0x3f3f3f3f
using namespace std;
int tot=1,k,n,m,cur[M],h[M],v[M],d[M],inq[M],p[M],a[M];
struct READ
{
int u,v,c,w;
}r[M*5];
struct edge
{
int from,to,cap,flow,cost,ne;
}E[200005];
void Addedge(int from,int to,int cap,int cost)
{
E[++tot]=(edge){from,to,cap,0,cost,h[from]};
h[from]=tot;
E[++tot]=(edge){to,from,0,0,-cost,h[to]};
h[to]=tot;
}
int bfs()
{
for (int i=1;i<=n;i++)
v[i]=0;
queue<int> q;
q.push(1);
v[1]=1;
d[1]=0;
while (!q.empty())
{
int x=q.front();
q.pop();
for (int i=h[x];i;i=E[i].ne)
{
edge e=E[i];
if (e.cap>e.flow&&!v[e.to])
{
v[e.to]=1;
d[e.to]=d[x]+1;
q.push(e.to);
}
}
}
return v
;
}
int dfs(int x,int a)
{
if (x==n||!a) return a;
int flow=0;
for (int &i=cur[x];i;i=E[i].ne)
{
edge &e=E[i];
if (d[e.to]!=d[x]+1) continue;
int f=dfs(e.to,min(a,e.cap-e.flow));
if (f)
{
a-=f;
e.flow+=f;
E[i^1].flow-=f;
flow+=f;
if (!a) break;
}
}
return flow;
}
int dinic()
{
int flow=0;
while (bfs())
{
for (int i=1;i<=n;i++)
cur[i]=h[i];
flow+=dfs(1,inf);
}
return flow;
}
int spfa(int &flow,int &cost)
{
for (int i=0;i<=n;i++)
d[i]=inf,inq[i]=0;
queue<int> q;
q.push(0);
inq[0]=1,d[0]=0,a[0]=inf,p[0]=0;
while (!q.empty())
{
int x=q.front();
q.pop();
inq[x]=0;
for (int i=h[x];i;i=E[i].ne)
{
edge e=E[i];
if (d[e.to]>d[x]+e.cost&&e.cap>e.flow)
{
d[e.to]=d[x]+e.cost;
p[e.to]=i;
a[e.to]=min(a[x],e.cap-e.flow);
if (!inq[e.to])
q.push(e.to),inq[e.to]=1;
}
}
}
if (d
==inf) return 0;
flow+=a
;
cost+=a
*d
;
int x=n;
while (x)
{
int y=p[x];
E[y].flow+=a
;
E[y^1].flow-=a
;
x=E[y].from;
}
return 1;
}
int mincost()
{
int flow=0,cost=0;
while (spfa(flow,cost));
return cost;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&r[i].u,&r[i].v,&r[i].c,&r[i].w);
Addedge(r[i].u,r[i].v,r[i].c,0);
}
printf("%d",dinic());
Addedge(0,1,k,0);
for (int i=1;i<=m;i++)
Addedge(r[i].u,r[i].v,inf,r[i].w);
printf(" %d\n",mincost());
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: