BZOJ 1834--网络扩容(最大流&费用流)

Posted Iscream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1834--网络扩容(最大流&费用流)相关的知识,希望对你有一定的参考价值。

    值得一做的好题。。。

题目链接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1834 

Solution

    第一问是赤果果的最大流。。。上模板就好。。。

    然后问扩流的最小费用。。。发现可以直接利用之前跑完最大流剩下的残余网络。

    在每一条边上额外加一条容量无限大的边,但是这样不能控制流的大小,所以要额外添加一个汇点S。

    从S向原起点连一条容量为k的边,再跑一遍费用流,就是第二问的答案。。。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define N 1010
#define inf 2000000000
using namespace std;
inline int Read(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int n,m,k,ans=0,cnt=1,S,T;
int hed[N],dis[N],l[N],q[200000];
bool vis[N];
struct edge{
	int l,r,nxt,v,c,t;
}e[50000];
void insert(int u,int v,int w,int c){
	cnt++;e[cnt].l=u;e[cnt].r=v;e[cnt].nxt=hed[u];hed[u]=cnt;e[cnt].v=w;e[cnt].c=0;e[cnt].t=c;
	cnt++;e[cnt].l=v;e[cnt].r=u;e[cnt].nxt=hed[v];hed[v]=cnt;e[cnt].v=0;e[cnt].c=0;e[cnt].t=-c;
}
bool BFS(){
	int head=0,tail=1,now;
	memset(dis,-1,sizeof(dis));
	dis[S]=1;q[1]=S;
	while(head!=tail){
		head++;
		now=q[head];
		for(int i=hed[now];i;i=e[i].nxt)
			if(e[i].v && dis[e[i].r]==-1){
				dis[e[i].r]=dis[now]+1;
				q[++tail]=e[i].r;
			}
	}
	return dis[T]!=-1;
}
int DFS(int x,int F){
	if(x==T)return F;
	int w,used=0;
	for(int i=hed[x];i;i=e[i].nxt)
		if(dis[e[i].r]==dis[x]+1){
			w=F-used;
			if(w>e[i].v)w=e[i].v;
			w=DFS(e[i].r,w);
			e[i].v-=w;
			e[i^1].v+=w;
			used+=w;
			if(used==F)return F;
		}
	if(!used)dis[x]=-1;
	return used;
}
void dinic(){
	while( BFS() ) 
		ans+=DFS(S,inf);
}
void ins(int u,int v,int w,int c){
	cnt++;e[cnt].l=u;e[cnt].r=v;e[cnt].v=w;e[cnt].nxt=hed[u];hed[u]=cnt;e[cnt].c=c;
	cnt++;e[cnt].l=v;e[cnt].r=u;e[cnt].v=0;e[cnt].nxt=hed[v];hed[v]=cnt;e[cnt].c=-c;
}
bool spfa(){
	int head=0,tail=1,now;
	for(int i=0;i<=n;i++)dis[i]=inf;
	q[1]=S;dis[S]=0;vis[S]=1;
	while(head!=tail){
		head++;
		now=q[head];
		for(int i=hed[now];i;i=e[i].nxt)
			if(e[i].v>0 && dis[now]+e[i].c<dis[e[i].r]){
				dis[e[i].r]=dis[now]+e[i].c;
				l[e[i].r]=i;
				if(!vis[e[i].r]){
					tail++;
					q[tail]=e[i].r;
					vis[e[i].r]=1;
				}
			}
		vis[now]=0;
	}
	return dis[T]!=inf;
}
int mincf(){
	int now,used=inf;
	now=l[T];
	while(now){
		if(used>e[now].v)used=e[now].v;
		now=l[e[now].l];
	}
	now=l[T];
	while(now){
		e[now].v-=used;
		e[now^1].v+=used;
		ans+=used*e[now].c;
		now=l[e[now].l];
	}
}
void Cost_Flow(){
	while( spfa() )
		ans+=mincf();
}
int main(){
	int u,v,w,c;
	n=Read();m=Read();k=Read();
	S=1;T=n;
	for(int i=1;i<=m;i++){
		u=Read();v=Read();w=Read();c=Read();
		insert(u,v,w,c);
	}
	dinic();
	printf("%d ",ans);
	ans=0;
	int tot=cnt;
	for(int i=2;i<=tot;i+=2)
         ins(e[i].l,e[i].r,inf,e[i].t);
	S=0;
	ins(0,1,k,0);
	Cost_Flow();
	printf("%d\n",ans);
	return 0;
}

  

  

This passage is made by Iscream-2001.

 

以上是关于BZOJ 1834--网络扩容(最大流&费用流)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1834 ZJOI2010网络扩容(费用流)

bzoj1834 网络扩容 网络流

BZOJ1834 [ZJOI2010] network 网络扩容

bzoj:1834: [ZJOI2010]network 网络扩容

BZOJ 1834 [ZJOI2010]network 网络扩容

[ZJOI2010][bzoj1834] 网络扩容 [费用流]