zoukankan      html  css  js  c++  java
  • EK算法 & Dinic

    2. 基本算法

    EK : (O(nm^2))

    Dinic: (O(n^2m))

    但其实上界非常宽松,一般 EK 能处理 (10^3-10^4) 的数据,Dinic (10^4-10^5)

    EK算法

    一般求最大流用不到,求最小费用流的时候 EK是核心算法

    dinic

    最大流

    (EK)

    /*
     * @Author: zhl
     * @Date: 2020-10-20 10:25:08
     */
    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i = a;i <= b;i++)
    #define repE(i,u) for(int i = head[u];~i;i = E[i].next)
    using namespace std;
    const int N = 1e3 + 10;
    const int M = 2e4 + 10;
    const int inf = 0x3f3f3f3f;
    struct Edge {
    	int to, flow, next;
    }E[M];
    
    int head[N], tot;
    void addEdge(int from, int to, int flow) {
    	E[tot] = Edge{ to,flow,head[from] };
    	head[from] = tot++;
    }
    
    int n, m, S, T;
    int d[N], pre[N];
    bool vis[N];
    
    bool bfs() {
    	queue<int>Q;
    	memset(vis, 0, sizeof vis);
    	Q.push(S); vis[S] = 1;
    	d[S] = inf;
    	while (!Q.empty()) {
    		int tp = Q.front(); Q.pop();
    		repE(i, tp) {
    			int u = E[i].to;
    			if (!vis[u] and E[i].flow) {
    				vis[u] = 1;
    				d[u] = min(d[tp], E[i].flow);
    				pre[u] = i;
    				if (u == T)return true;
    				Q.push(u);
    			}
    		}
    	}
    	return false;
    }
    
    int EK() {
    	int ans = 0;
    	while (bfs()) {
    		ans += d[T];
    		for (int i = T; i != S; i = E[pre[i] ^ 1].to) {
    			E[pre[i]].flow -= d[T];
    			E[pre[i] ^ 1].flow += d[T];
    		}
    	}
    	return ans;
    }
    int main() {
    	scanf("%d%d%d%d", &n, &m, &S, &T);
    	memset(head, -1, sizeof head);
    
    	rep(i, 1, m) {
    		int a, b, c;
    		scanf("%d%d%d", &a, &b, &c);
    		addEdge(a, b, c);
    		addEdge(b, a, 0);
    	}
    
    	printf("%d
    ", EK());
    }
    

    (Dinic)

    /*
     * @Author: zhl
     * @Date: 2020-10-20 11:09:59
     */
    #include<bits/stdc++.h>
    //#define int long long
    using namespace std;
    
    const int N = 1e4 + 10, M = 1e5 + 10, inf = 1e9;
    int n, m, s, t, tot, head[N];
    int ans, dis[N], cur[N];
    
    struct Edge {
    	int to, next, flow;
    }E[M<<1];
    
    void addEdge(int from, int to, int w) {
    	E[tot] = Edge{ to,head[from],w };
    	head[from] = tot++;
    	E[tot] = Edge{ from,head[to],0 };
    	head[to] = tot++;
    }
    
    int bfs() {
    	for (int i = 1; i <= n; i++) dis[i] = -1;
    	queue<int>Q;
    	Q.push(s);
    	dis[s] = 0;
    	cur[s] = head[s];
    
    	while (!Q.empty()) {
    		int u = Q.front();
    		Q.pop();
    		for (int i = head[u]; ~i; i = E[i].next) {
    			int v = E[i].to;
    			if (E[i].flow && dis[v] == -1) {
    				Q.push(v);
    				dis[v] = dis[u] + 1;
    				cur[v] = head[v];
    				if (v == t)return 1; //分层成功
    			}
    		}
    	}
    	return 0;
    }
    
    int dfs(int x, int sum) {
    	if (x == t)return sum;
    	int k, res = 0;
    	for (int i = cur[x]; ~i && res < sum; i = E[i].next) {
    		cur[x] = i;
    		int v = E[i].to;
    		if (E[i].flow > 0 && (dis[v] == dis[x] + 1)) {
    			k = dfs(v, min(sum, E[i].flow));
    			if (k == 0) dis[v] = -1; //不可用
    			E[i].flow -= k;E[i ^ 1].flow += k;
    			res += k;sum -= k;
    		}
    	}
    	return res;
    }
    
    int Dinic() {
    	int ans = 0;
    	while (bfs()) {
            ans += dfs(s,inf);
    	}
    	return ans;
    }
    
    signed main() {
    	scanf("%d%d%d%d",&n,&m,&s,&t);
    	memset(head, -1, sizeof(int) * (n + 10));
    	for (int i = 1; i <= m; i++) {
    		int a, b, w;
    		scanf("%d%d%d",&a, &b, &w);
    		addEdge(a, b, w);
    	}
    	printf("%d
    ",Dinic());
    }
    
  • 相关阅读:
    Jaxb2 实现JavaBean与xml互转
    标准输入与标准输出
    linux 一行一行的读取文件
    linux $* 和$@ if [ ](字符串比较)
    scala 学习(三)——Array和ArrayBuffer
    Shell编程(六)awk工具
    Shell编程(五)脚本语法
    Shell编程(四)Shell变量
    Shell编程(三)Shell特性
    Shell编程(一)概览
  • 原文地址:https://www.cnblogs.com/sduwh/p/13849177.html
Copyright © 2011-2022 走看看