ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【ZJOI2010】【BZOJ1834】—网络扩容(最大流+最小费用最大流)

2019-01-27 16:02:46  阅读:325  来源: 互联网

标签:return 最大 int res des flow BZOJ1834 ZJOI2010 dis


传送门

第一问都不用说了吧

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

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

至于只多kkk个单位,新建一个源点向111连一条流量为kkk的边,
nnn向汇点连一条为kkk的边,把第一次最大流的边费用设为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()<<'\n';
}

标签:return,最大,int,res,des,flow,BZOJ1834,ZJOI2010,dis
来源: https://blog.csdn.net/qq_42555009/article/details/86666774

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有