• 【网络流】


    ISAP 最大流 赛事首选
    无向图将反向边权值改为v即可。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int oo = 0x7f7f7f7f;
    const int N = 10010;
    const int M = 100010;
    
    template <typename T>
    T read(){
        T n(0), f(1);
        char ch = getchar();
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
        for(; isdigit(ch); ch = getchar()) n = n*10 + ch-48;
        return n*f;
    }
    #define read() read<int>()
    
    int n, m, e, S, T;
    int to[M<<1], nxt[M<<1], w[M<<1];
    int Begin[N], h[N], gap[N];
    
    void addedge(int x, int y, int v){
        to[e] = y; nxt[e] = Begin[x]; w[e] = v; Begin[x] = e++;
        to[e] = x; nxt[e] = Begin[y]; w[e] = 0; Begin[y] = e++;
    }
    
    int dfs(int u, int cost){
        if(u == T) return cost;
        int minh = n-1, lv = cost, d;
        for(int i = Begin[u]; i != -1; i = nxt[i]){
            int v = to[i], val = w[i];
            if(val > 0){
                if(h[v] + 1 == h[u]){
                    d = min(lv, val);
                    d = dfs(v, d);
                    w[i] -= d;
                    w[i^1] += d;
                    lv -= d;
                    if(h[S] >= n) return cost-lv;
                    if(!lv) break;
                }
                minh = min(minh, h[v]);
            }
        }
        if(lv == cost){
            --gap[h[u]];
            if(!gap[h[u]]) h[S] = n;
            h[u] = minh+1;
            ++gap[h[u]];
        }
        return cost-lv;
    }
    
    int sap(int s, int t){
        S = s; T = t;
        memset(gap, 0, sizeof(gap));
        memset(h, 0, sizeof(h));
        gap[s] = n;
        int ret = 0;
        while(h[s] < n){
            ret += dfs(s, oo);
        }
        return ret;
    }
    
    int main(){
        memset(Begin, -1, sizeof(Begin));
        int s, t;
        n = read(); m = read();
        s = read(); t = read();
        for(int i = 1; i <= m; ++i){
            int x, y, v;
            x = read(); y = read(); v = read();
            addedge(x, y, v);
        }
    
        printf("%d
    ", sap(s, t));
        return 0;
    }
    

    增广路算法求最大流
    模板LG P3376
    DFS太慢,EK算法其实也很慢....(既然是NOIP选手不掌握fastest也没问题吧)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int oo = 0x7f7f7f7f;
    const int N = 10010;
    
    template <typename T>
    T read(){
    	T n(0), f(1);
    	char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    	for(; isdigit(ch); ch = getchar()) n = n*10 + ch-48;
    	return n*f;
    }
    
    struct Edge{
    	int u, v, cap, flow;
    	Edge(int from, int to, int c, int f):u(from), v(to), cap(c), flow(f){}
    };
    
    int n, m;
    int a[N], p[N];
    vector<Edge> edges;
    vector<int> G[N];
    
    #define pb push_back
    
    void init(){
    	for(int i = 1; i <= n; ++i) G[i].clear();
    	edges.clear();
    }
    
    void addedge(int u, int v, int cap){
    	edges.pb(Edge(u, v, cap, 0));
    	edges.pb(Edge(v, u, 0, 0));
    	int tm = edges.size();
    	G[u].pb(tm-2);
    	G[v].pb(tm-1);
    }
    
    int EK(int s, int t){
    	int flow = 0;
    	for(;;){
    		memset(a, 0, sizeof(a));
    		queue<int> Q;
    		Q.push(s);
    		a[s] = oo;
    		while(!Q.empty()){
    			int x = Q.front(); Q.pop();
    			for(int i = 0; i < G[x].size(); ++i){
    				Edge& e = edges[G[x][i]];
    				if(!a[e.v] && e.cap > e.flow){
    					p[e.v] = G[x][i];
    					a[e.v] = min(a[x], e.cap-e.flow);
    					Q.push(e.v);
    				}
    			}
    			if(a[t]) break;
    		}
    		if(!a[t]) break;
    		for(int i = t; i != s; i = edges[p[i]].u){
    			edges[p[i]].flow += a[t];
    			edges[p[i]^1].flow -= a[t];
    		}
    		flow += a[t];
    	}
    	return flow;
    }
    
    int main(){
    	int s, t;
    	n = read<int>(); m = read<int>();
    	s = read<int>(); t = read<int>();
    
    	init();
    	
    	for(int i = 1; i <= m; ++i){
    		int u, v, w;
    		u = read<int>();
    		v = read<int>();
    		w = read<int>();
    		addedge(u, v, w);
    	}
    	
    	printf("%d
    ", EK(s, t));
    	
    	return 0;
    }
    

    最小费用最大流
    模板LG P3381
    用Bellmanford求

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const int N = 5010;
    const int M = 50010;
    const int oo = 0x7f7f7f7f;
    
    template <typename T>
    T read(){
    	T n(0), f(1);
    	char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    	for(; isdigit(ch); ch = getchar()) n = n*10 + ch-48;
    	return n*f;
    }
    
    #define read() read<int>()
    
    struct Edge{
    	int from, to, cap, flow, cost;
    	Edge(int u, int v, int c, int f, int val):from(u), to(v), cap(c), flow(f), cost(val){}
    };
    
    int n, m;
    vector<Edge> edges;
    vector<int> G[N];
    int a[N], d[N], p[N], inq[N];
    
    #define pb push_back
    
    void addedge(int x, int y, int w, int v){
    	edges.pb(Edge(x, y, w, 0, v));
    	edges.pb(Edge(y, x, 0, 0, -v));
    	int tm = edges.size();
    	G[x].pb(tm-2);
    	G[y].pb(tm-1);
    }
    
    void init(){
    	for(int i = 1; i <= n; ++i) G[i].clear();
    	edges.clear();
    }
    
    bool BMFD(int s, int t, int& flow, ll& cost){
    	memset(inq, 0, sizeof(inq));
    	for(int i = 1; i <= n; ++i) d[i] = oo;
    	d[s] = p[s] = 0; a[s] = oo; inq[s] = 1;
    
    	queue<int> Q;
    	Q.push(s);
    	while(!Q.empty()){
    		int u = Q.front(); Q.pop();
    		inq[u] = 0;
    		for(int i = 0; i < G[u].size(); ++i){
    			Edge& e = edges[G[u][i]];
    			if(e.cap > e.flow && d[e.to] > d[u]+e.cost){
    				d[e.to] = d[u] + e.cost;
    				a[e.to] = min(a[u], e.cap-e.flow);
    				p[e.to] = G[u][i];
    				if(!inq[e.to]){ Q.push(e.to); inq[e.to] = 1; }
    			}
    		}
    	}
    	if(d[t] == oo) return false;
    	flow += a[t];
    	cost += 1ll*d[t]*a[t];
    	for(int i = t; i != s; i = edges[p[i]].from){
    		edges[p[i]].flow += a[t];
    		edges[p[i]^1].flow -= a[t];
    	}
    	return true;
    }
    
    int MCMF(int s, int t, ll& cost){
    	int flow = 0; cost = 0;
    	while(BMFD(s, t, flow, cost));
    	return flow;
    }
    
    int main(){
    	int s, t;
    
    	n = read(); m = read();
    	s = read(); t = read();
    	init();
    	
    	for(int i = 1; i <= m; ++i){
    		int x, y, w, v;
    		x = read(); y = read();
    		w = read(); v = read();
    		addedge(x, y, w, v);
    	}
    
    	ll cost = 0;
    	printf("%d ", MCMF(s, t, cost));
    	printf("%lld
    ", cost);
    	return 0;
    }
    
  • 相关阅读:
    牛客 小乐乐和25
    codeforces 1303 D 二进制瞎搞
    codeforces 1307 D 最短路bz+贪心
    codeforces 1316 C math
    codeforces 1328E LCA
    codeforces 1335 E2 思维
    codeforces 1335 E1 思维
    codeforces 1342 D 贪心+后缀和
    codeforces 1348D (思维+贪心)
    codeforces 1362 E 进制的性质
  • 原文地址:https://www.cnblogs.com/hanser/p/7816283.html
Copyright © 2020-2023  润新知