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

【BZOJ】【1834】【ZJOI2010】Network 网络扩容

2015-03-18 00:22 453 查看

网络流/费用流

  这题……我一开始sb了。

  第一问简单的最大流……

  第二问是要建费用流的图的……但是是在第一问的最大流跑完以后的残量网络上建,而不是重建……

  我们令残量网络上原有的弧的费用全部为0(因为如果还能走就不需要扩容),而新加的弧容量为INF,费用为给定的w[i]。

  然后跑费用流就好了……这样建的话如果是不用扩容的边它就会自己走费用为0的弧。

RE/TLE:费用流扩展时的队列/边集数组的大小 M 开小了,队列长度从N改成M,M大小从20000改成50000后AC

/**************************************************************
Problem: 1834
User: Tunix
Language: C++
Result: Accepted
Time:36 ms
Memory:3824 kb
****************************************************************/

//BZOJ 1834
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=0,sign=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
return v*sign;
}
const int N=1002,M=50000,INF=~0u>>2;
typedef long long LL;
/******************tamplate*********************/
int n,m,k,ans;
struct edge{int from,to,v,c,w;};
struct Net{
edge E[M],G[M];
int head
,next[M],cnt;
void ins(int x,int y,int v,int c){
E[++cnt]=(edge){x,y,v,0,c};
next[cnt]=head[x]; head[x]=cnt;
}
void add(int x,int y,int v,int c){
ins(x,y,v,c); ins(y,x,0,-c);
}
void Ins(int x,int y,int v,int c){
E[++cnt]=(edge){x,y,v,c,0};
next[cnt]=head[x]; head[x]=cnt;
}
void Add(int x,int y,int v,int c){
Ins(x,y,v,c); Ins(y,x,0,-c);
}
int s,t,d
,Q[M];
bool mklevel(){
F(i,1,n) d[i]=-1;
d[s]=0;
int l=0,r=-1;
Q[++r]=s;
while(l<=r){
int x=Q[l++];
for(int i=head[x];i;i=next[i])
if (d[E[i].to]==-1 && E[i].v){
d[E[i].to]=d[x]+1;
Q[++r]=E[i].to;
}
}
return d[t]!=-1;
}
int dfs(int x,int a){
if (x==t) return a;
int flow=0;
for(int i=head[x];i && flow<a;i=next[i])
if (E[i].v && d[E[i].to]==d[x]+1){
int f=dfs(E[i].to,min(a-flow,E[i].v));
E[i].v-=f;
E[i^1].v+=f;
flow+=f;
}
if (!flow) d[x]=-1;
return flow;
}
void Dinic(){
while(mklevel()) ans+=dfs(s,INF);
}
int from[M];
bool inq
;
bool spfa(){
int l=0,r=-1;
F(i,0,n) d[i]=INF;
d[s]=0; Q[++r]=s; inq[s]=1;
while(l<=r){
int x=Q[l++];
inq[x]=0;
for(int i=head[x];i;i=next[i])
if (E[i].v>0 && d[x]+E[i].c<d[E[i].to]){
d[E[i].to]=d[x]+E[i].c;
from[E[i].to]=i;
if (!inq[E[i].to]){
Q[++r]=E[i].to;
inq[E[i].to]=1;
}
}
}
return d
!=INF;
}
void mcf(){
int x=INF;
for(int i=from[t];i;i=from[E[i].from])
x=min(x,E[i].v);
for(int i=from[t];i;i=from[E[i].from]){
E[i].v-=x;
E[i^1].v+=x;
ans+=x*E[i].c;
}
}
void build(){
int t=cnt;
for(int i=2;i<=t;i+=2)
Add(E[i].from,E[i].to,INF,E[i].w);
}
void init(){
n=getint(); m=getint(); k=getint();
int x,y,z,w;
cnt=1;
s=1; t=n;
F(i,1,m){
x=getint(); y=getint(); z=getint(); w=getint();
add(x,y,z,w);
}
Dinic(); build();
printf("%d ",ans);
ans=0; s=0;
ins(s,1,k,0);
while(spfa()) mcf();
printf("%d\n",ans);
}
}G1;

int main(){
#ifndef ONLINE_JUDGE
freopen("1834.in","r",stdin);
freopen("1834.out","w",stdout);
#endif
G1.init();
return 0;
}


View Code

1834: [ZJOI2010]network 网络扩容

Time Limit: 3 Sec Memory Limit: 64 MB
Submit: 1976 Solved: 986
[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

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