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

bzoj1834(网络流加费用流)

2016-03-08 18:53 381 查看

1834: [ZJOI2010]network 网络扩容

Time Limit: 3 Sec Memory Limit: 64 MB

Submit: 2390 Solved: 1206

[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

解题思路:第一问就是最大流,然后第二问,可以对在建m条边,只是产生费用,再来一个源点,到一的容量为K。跑一边费用流。

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

using namespace std;

int n,m,k,len,ans;

int from[21000],to[21000],cc[21000],ww[21000],next[21000];

int h[1100];

int dis[1100];

int q[1000000];

bool og[1100];

int pre[1100];

int x[5100],y[5100],c[5100],w[5100];

inline int read()

{

char y; int x=0,f=1; y=getchar();

while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}

while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}

return x*f;

}

void insert(int x,int y,int c,int w)

{

++len;

from[len]=x; to[len]=y; cc[len]=c; ww[len]=w; next[len]=h[x]; h[x]=len;

}

int dicnic(int sum,int now)

{

if (now==n) return sum;

int u=h[now]; int sug=0;

while (u!=0)

{

if (cc[u]>0 && dis[now]+1==dis[to[u]])

{

int s=dicnic(min(cc[u],sum-sug),to[u]);

if (s>0)

{

sug+=s;

cc[u]-=s; cc[u^1]+=s;

if (sug==sum) return sum;

}

}

u=next[u];

}

if (sug==0) dis[now]=-1;

return sug;

}

bool bfs()

{

memset(dis,-1,sizeof(dis));

dis[1]=1; int tail=0,head=0; ++tail; q[tail]=1;

while (head<tail)

{

++head;

int u=h[q[head]];

while (u!=0)

{

if (cc[u]>0 && dis[to[u]]==-1)

{

dis[to[u]]=dis[q[head]]+1;

++tail; q[tail]=to[u];

}

u=next[u];

}

}

if (dis
!=-1) return true; else return false;

}

bool spfa()

{

memset(dis,0x7e,sizeof(dis));

memset(og,true,sizeof(og));

og[0]=false;

dis[0]=0; int tail=1,head=0; q[tail]=0;

while (head<tail)

{

++head;

int u=h[q[head]];

while (u!=0)

{

if (cc[u]>0 && dis[to[u]]>dis[q[head]]+ww[u])

{

pre[to[u]]=u;

dis[to[u]]=dis[q[head]]+ww[u];

if (og[to[u]])

{

og[to[u]]=false;

++tail; q[tail]=to[u];

}

}

u=next[u];

}

og[q[head]]=true;

}

if (dis
<1000000) return true;else return false;

}

void mcf()

{

int now=n; int zan=0x7fffffff;

while (now!=0)

{

zan=min(zan,cc[pre[now]]);

now=from[pre[now]];

}

now=n;

while (now!=0)

{

cc[pre[now]]-=zan; cc[pre[now]^1]+=zan;

ans+=zan*ww[pre[now]];

now=from[pre[now]];

}

}

int main()

{

n=read(); m=read(); k=read();

len=1;

for (int i=1;i<=m;++i)

{

x[i]=read(); y[i]=read(); c[i]=read(); w[i]=read();

insert(x[i],y[i],c[i],0); insert(y[i],x[i],0,0);

}

int sum=0;

while (bfs())

{

sum+=dicnic(0x7fffffff,1);

}

printf("%d ",sum);

insert(0,1,k,0); insert(1,0,-k,0);

for (int i=1;i<=m;++i)

{

insert(x[i],y[i],k,w[i]); insert(y[i],x[i],0,-w[i]);

}

ans=0;

while (spfa())

{

mcf();

}

printf("%d",ans);

}

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