zoukankan      html  css  js  c++  java
  • BZOJ 1834 【ZJOI2010】 network 网络扩容

    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的答案。

    HINT

    30%的数据中,N<=100

    100%的数据中,N<=1000,M<=5000,K<=10
     
      网络流与费用流二合一233~
      首先第一问显然没有什么好讲的,直接跑一遍最大流即可。
      接下来是第二问。既然$k$这么小,那么我们保留下跑最大流后的残量网络,显然残量网络中有流量的边都是有可以直接流的,并且不需要任何费用。
      然后我们对于原图中的每一条边,新建一条容量为$inf$,费用为扩容费用 的边。接下来新建一个源点,向$1$号点连一条容量为$k$,费用为$0$的边,控制一下流量。
      最后跑一遍最小费用最大流即可。
      下面贴代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define maxn 1010
    #define maxm 20010
    #define INF (1<<25)
    
    using namespace std;
    typedef long long llg;
    
    struct data{
    	int u,v,c,w;
    }s[maxm];
    int n,m,K,d[maxn],dep[maxn],ans,S,fa[maxn];
    int head[maxn],next[maxm],to[maxm],c[maxm],f[maxm],tt=1;
    bool w[maxn];
    
    int getint(){
    	int w=0;bool q=0;
    	char c=getchar();
    	while((c>'9'||c<'0')&&c!='-') c=getchar();
    	if(c=='-') c=getchar(),q=1;
    	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    	return q?-w:w;
    }
    
    bool bfs(){
    	int l=0,r=0;
    	for(int i=1;i<=n;i++) dep[i]=-1;
    	dep[1]=1; d[r++]=1;
    	while(l!=r){
    		int u=d[l++];
    		for(int i=head[u],v;v=to[i],i;i=next[i])
    			if(c[i] && dep[v]==-1) dep[v]=dep[u]+1,d[r++]=v;
    	}
    	return dep[n]!=-1;
    }
    
    int dfs(int u,int now){
    	if(u==n) return now;
    	if(!now) return 0;
    	int low=0;
    	for(int i=head[u],v,res;v=to[i],i;i=next[i])
    		if(c[i] && dep[v]==dep[u]+1){
    			res=dfs(v,min(now,c[i])); low+=res;
    			c[i]-=res; c[i^1]+=res; now-=res;
    		}
    	if(!low) dep[u]=-1;
    	return low;
    }
    
    bool spfa(){
    	int l=0,r=0;
    	for(int i=1;i<=n;i++) dep[i]=-1,w[i]=0;
    	dep[S]=0; d[r++]=S; w[S]=1;
    	while(l!=r){
    		int u=d[l++]; w[u]=0; if(l==maxn) l=0;
    		for(int i=head[u],v;v=to[i],i;i=next[i])
    			if(c[i] && (dep[v]==-1 || dep[v]>dep[u]+f[i])){
    				dep[v]=dep[u]+f[i]; fa[v]=i;
    				if(!w[v]){
    					d[r++]=v; w[v]=1;
    					if(r==maxn) r=0;
    				}
    			}
    	}
    	return dep[n]!=-1;
    }
    
    int get(){
    	int now=INF,ans=0;
    	for(int u=n;u!=S;u=to[fa[u]^1]) now=min(now,c[fa[u]]),ans+=f[fa[u]];
    	for(int u=n;u!=S;u=to[fa[u]^1]) c[fa[u]]-=now,c[fa[u]^1]+=now;
    	return now*ans;
    }
    
    int main(){
    	File("a");
    	n=getint(); m=getint(); K=getint();
    	for(int i=1,u,v;i<=m;i++){
    		s[i].u=getint(),s[i].v=getint();
    		s[i].c=getint(),s[i].w=getint();
    		u=s[i].u; v=s[i].v;
    		to[++tt]=v;next[tt]=head[u];head[u]=tt;
    		to[++tt]=u;next[tt]=head[v];head[v]=tt;
    		c[tt-1]=s[i].c;
    	}
    	while(bfs()) ans+=dfs(1,INF);
    	printf("%d",ans);
    	for(int i=1,u,v;i<=m;i++){
    		u=s[i].u,v=s[i].v;
    		to[++tt]=v;next[tt]=head[u];head[u]=tt;
    		to[++tt]=u;next[tt]=head[v];head[v]=tt;
    		c[tt-1]=INF; f[tt-1]=s[i].w; f[tt]=-s[i].w;
    	}
    	S=n+1; ans=0;
    	to[++tt]=1;next[tt]=head[S];head[S]=tt; c[tt]=K;
    	to[++tt]=S;next[tt]=head[1];head[1]=tt;
    	while(spfa()) ans+=get();
    	printf(" %d",ans);
    	return 0;
    }
  • 相关阅读:
    来自CSDN的精华网址
    图片及生成缩略图
    那位对DataGrid控熟悉?能否请教一下
    关于用.NET写邮件发送系统的问题
    JavaScript]几种常用的表单输入判断
    VB C# 语法对比图
    给上传的图片加上一个水印
    那位对DataGrid控熟悉?能否请教一下
    一句话木马的免杀(转)
    SOAP注入攻击详解(转)
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6055436.html
Copyright © 2011-2022 走看看