zoukankan      html  css  js  c++  java
  • BZOJ 1834网络扩容(最大流&费用流) Iscream

    1834: [ZJOI2010]network 网络扩容

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

    题目链接:

        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.

  • 相关阅读:
    第九十一天 how can I 坚持 技术-永远的技术
    第九十天 how can I 坚持
    Java控制台中输入中文输出乱码的解决办法
    【体系结构】转移预测器设计与比较1
    Ubuntu 13.04 用Sublime Text 2 编译运行 JAVA
    HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
    个人重构机房收费系统之报表
    快速排序的递归和非递归实现
    HDU 3721 Building Roads (2010 Asia Tianjin Regional Contest)
    体验决定深度,知识决定广度。你的人生是什么呢? 操蛋和扯蛋没必要纠结 唯有继续
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/7747983.html
Copyright © 2011-2022 走看看