zoukankan      html  css  js  c++  java
  • 【BZOJ1497】【NOI2006】—最大获利(网络流/最小割)

    传送门

    考虑到一个问题:

    建立中转站是花钱,而满足用户需求是获利
    怎么将这两个东西结合起来?

    换个角度:

    假设我们能满足所有用户的要求
    那如果我们选择不满足客户的需求不就是也在花钱了吗
    或者说我们把客户的需求看做要花那么多钱

    那我们现在就有两个选择了

    要么花钱修中转站来满足客户需求
    要么花钱来解决客户的需求

    我们现在要做的就是找到一种花费最少的方案
    来解决所有客户的需求

    如果我们把解决需求看做是断开一条边的话
    那我们从源点连向所有的中转站,所有的客户连向汇点,有需求的互相连边,花费为边权

    我们就是在求这个图的最小割

    又由于放弃客户和建中转站显然是矛盾的

    连一条为infinf的边就可以了


    UPDATE:UPDATE:现在看起来好像就是最大权闭合子图
    原谅那时的我太naiivenaiive不知道这东西

    #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=150005;
    const int M=400005;
    const int inf=20030224;
    int n,m,cnt=1,adj[N],tp[N],nxt[M],to[M],cap[M],lev[N],str,des,tot;
    inline void addedge(int u,int v,int w){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,cap[cnt]=w;
    	nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,cap[cnt]=0;
    }
    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 now=dinic(v,min(flow-res,cap[e]));
    			cap[e]-=now,cap[e^1]+=now,res+=now;
    			if(flow==res)return res;
    		}
    	}
    	return res;
    }
    inline int solve(){
    	int res=0;
    	while(bfs()){
    		memcpy(tp,adj,sizeof(adj));
    		res+=dinic(str,inf);
    	}
    	return res;
    }
    int main(){
    	n=read(),m=read();str=n+m+1,des=str+1;
    	for(int i=1;i<=n;i++){
    		int p=read();
    		addedge(str,i,p);
    	}
    	for(int i=1;i<=m;i++){
    		int a=read(),b=read(),c=read();
    		addedge(a,i+n,inf),addedge(b,i+n,inf);
    		addedge(i+n,des,c),tot+=c;
    	}
    	tot-=solve();
    	cout<<tot<<'
    ';
    }
    
  • 相关阅读:
    java+selenium自动化-IE浏览器搭建自动化环境
    python中的opencv
    随机森林参数说明
    剑指offer
    Python中常用的包--sklearn
    Anaconda安装,jupyter notebook 使用说明
    C++中的Public 、Private、Protected 区别
    C++类中的Static关键字二
    C++类中的Static关键字
    c语言二级指针内存模型
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366329.html
Copyright © 2011-2022 走看看