zoukankan      html  css  js  c++  java
  • 网络流之最大流

    网络流之最大流

    例题

    网络流一般可以解决形如以上的类似匹配的问题,将复杂,抽象的问题转化成图,在图上跑bfs,dfs,从而简化问题难度。

    如此题,有N个插头,M个插座,部分插头可以转化为其他插头,插座与一个插头适配,问最小没有被插的插座的数量,我们可以设一个源点连向插头,插头连向插座,再将插座连想汇点跑最大流即可出答案。

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const ll inf=1e18,N =300007, M = 300007;
    struct node {
    	ll to, next;
    	ll w;
    }edge[M];
    ll tot, head[N];
    void addedge(ll u, ll v, ll w) {
    	edge[++tot].to = v; edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot;
    	edge[++tot].to = u; edge[tot].w = 0; edge[tot].next = head[v]; head[v] = tot;
    }
    ll maxflow;
    ll n,m,s,t,k,cnt;
    ll deep[N]; //层级数,其实应该是level
    ll now[M]; //当前弧优化
    queue <ll> q;
    bool bfs() {
    	for(int i = 1;i <= t; i++) deep[i] = inf;
    	while(!q.empty()) q.pop();
    	q.push(s); deep[s] = 0; now[s] = head[s];
    	while(!q.empty()) {
    		ll u = q.front(); q.pop();
    		for(int i = head[u]; i; i = edge[i].next) {
    			ll v = edge[i].to;
    			if(edge[i].w && deep[v] == inf) {
    				q.push(v);
    				now[v] = head[v];
    				deep[v] = deep[u] + 1;
    				if(v == t) return 1;
    			}
    		}
    	}
    	return 0;
    }
    //flow是整条增广路对最大流的贡献,rest是当前最小剩余容量,用rest去更新flow
    ll dfs(ll u, ll flow) {
    	if(u == t) return flow;
    	ll ans = 0;
    	for(int i = now[u];i && flow; i = edge[i].next) {
    		now[u] = i; //当前弧优化(避免重复遍历从x出发的不可拓展的边)
    		ll v = edge[i].to;
    		if(edge[i].w && deep[v] == deep[u]+1) { //必须是下一层并且剩余容量大于0
    			ll k = dfs(v, min(flow, edge[i].w)); //取最小
    			if(!k) deep[v] = inf; //剪枝,去掉增广完毕的点
    			edge[i].w -= k; //回溯时更新
    			edge[i^1].w += k; //成对变换
    			ans += k;
    			flow -= k;
    		}
    	}
    	return ans;
    }
    void dinic() {
    	while(bfs())
    		maxflow += dfs(s, inf);
    }
    string s1,s2;
    map<string,ll>ma;
    int main(){
    	scanf("%lld",&n);
    	tot=1;
    	s=1000,t=1001;
    	for(int i=1;i<=n;i++){
    		cin>>s1;
    		if(ma[s1]==0){
    			ma[s1]=++cnt;
    			addedge(ma[s1],t,1);
    		}
    	}
    	scanf("%lld",&m);
    	for(int i=1;i<=m;i++){
    		cin>>s1>>s2;
    		addedge(s,++cnt,1);
    		if(ma[s2]==0){
    			ma[s2]=++cnt;
    			addedge(cnt-1,ma[s2],1);
    		}
    		else{
    			addedge(cnt,ma[s2],1);
    		}
    	}
    	scanf("%lld",&k);
    	for(int i=1;i<=k;i++){
    		cin>>s1>>s2;
    		if(ma[s1]==0){
    			ma[s1]=++cnt;
    		}
    		if(ma[s2]==0){
    			ma[s2]=++cnt;
    		}
    		addedge(ma[s1],ma[s2],inf);
    	}
    	dinic();
    	printf("%lld
    ",m-maxflow);
    }
    
  • 相关阅读:
    set desktop for aliyun ubuntu
    【深度学习】paddlepaddle——基于卷积神经网络的手写字识别案例
    【深度学习】paddlepaddle基础语法
    【深度学习】TensorFlow——理解张量
    【深度学习】TensorFlow——图详解
    【深度学习】TensorFlow——变量op
    【深度学习】TensorFlow——实现线性回归案例
    【深度学习】TensorFlow——理解会话
    【深度学习】TensorFlow——初识tensorflow
    【机器学习】量化策略
  • 原文地址:https://www.cnblogs.com/whitelily/p/14034699.html
Copyright © 2011-2022 走看看