zoukankan      html  css  js  c++  java
  • 【ZJOI2010】【BZOJ1834】—网络扩容(最大流+最小费用最大流)

    传送门

    第一问都不用说了吧

    对于第二问
    考虑到扩容一个单位就可以多通过一个单位的流
    我们可以把扩容看成流过这条边,扩容费用作为费用

    那么就在原图的基础上再跑一个最小费用最大流
    在每条边两端连一个流量为infinf,费用为ww的边

    至于只多kk个单位,新建一个源点向11连一条流量为kk的边,
    nn向汇点连一条为kk的边,把第一次最大流的边费用设为0就可以了

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=1505;
    const int M=20005;
    const int inf=19260817;
    int n,m,k,cnt=1,adj[N],nxt[M<<1],to[M<<1],cap[M<<1],lev[N],val[M<<1],vis[N],tp[N],str,des;
    inline void addedge(int u,int v,int w,int c){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,cap[cnt]=w,val[cnt]=c;
    	nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,cap[cnt]=0,val[cnt]=-c;
    }
    inline bool bfs(){
    	memset(lev,-1,sizeof(lev));
    	queue<int> q;
    	q.push(str),lev[str]=0;
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int e=adj[u];e;e=nxt[e]){
    			int v=to[e];
    			if(cap[e]>0&&lev[v]==-1){
    				lev[v]=lev[u]+1;
    				q.push(v);
    				if(v==des)return true;
    			}
    		}
    	}
    	return false;
    }
    int dinic(int u,int flow){
    	if(u==des)return flow;
    	int res=0;
    	for(int &e=tp[u];e;e=nxt[e]){
    		int v=to[e];
    		if(cap[e]>0&&lev[v]==lev[u]+1){
    			int mn=dinic(v,min(flow-res,cap[e]));
    			res+=mn,cap[e]-=mn,cap[e^1]+=mn;
    			if(res==flow)return res;
    		}
    	}
    	return res;
    }
    inline int solve(){
    	int res=0;
    	while(bfs()){
    		memcpy(tp,adj,sizeof(adj));
    		res+=dinic(str,inf);
    	}
    	return res;
    }
    int a[M],b[M],c[M],d[M],ans;
    int pre[N],pos[N],dis[N],flow[N];
    inline bool spfa(){
        memset(dis,127,sizeof(dis));
        int Inf=dis[0];
        memset(vis,0,sizeof(vis));
        queue<int> q;
        for(int i=1;i<=n;i++)pre[i]=-1;
        dis[str]=0,vis[str]=1,pre[str]=0,flow[str]=0x7fffffff,q.push(str);
        while(!q.empty()){
            int u=q.front();q.pop();
            vis[u]=0;
            for(int e=adj[u];e;e=nxt[e]){
                int v=to[e];
                if(cap[e]>0&&dis[v]>dis[u]+val[e]){
                    dis[v]=dis[u]+val[e],pre[v]=u,pos[v]=e,flow[v]=min(flow[u],cap[e]);
                    if(!vis[v]){
                        vis[v]=1,q.push(v);
                    }
                }
            }
        }
        if(dis[des]>=Inf)return 0;
        return 1;
    }
    inline int EK(int res=0){
        while(spfa()){
        	int u=des;
        	while(u!=str){
        		cap[pos[u]]-=flow[des];
        		cap[pos[u]^1]+=flow[des];
        		u=pre[u];
    		}
            res+=(dis[des]*flow[des]);
        }
        return res;
    }
    int main(){
    	n=read(),m=read(),k=read();
    	for(int i=1;i<=m;i++){
    		a[i]=read(),b[i]=read(),c[i]=read(),d[i]=read();
    		addedge(a[i],b[i],c[i],0);
    	}
    	str=1,des=n;
    	cout<<(ans=solve())<<" "; 
    	str=n+1,des=n+2;
    	for(int i=1;i<=m;i++){
    		addedge(a[i],b[i],inf,d[i]);
    	}
    	addedge(str,1,k,0),addedge(n,des,k,0);
    	cout<<EK()<<'
    ';
    }
    
  • 相关阅读:
    Qt应用如何发布
    关于在windows下部署发布QT程序的总结
    干净地发布QT程序
    解析 Qt 程序在Windows 下发布
    Qt 5.2.0 和 VS 2012集成
    Unable to find a qt build, to solve this problem specify a qt build
    运行python程序不显示cmd的方法
    py2exe使用方法
    python 类
    在Pygtk和Glade使用Gtkbuilder
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366324.html
Copyright © 2011-2022 走看看