• 最小费用最大流 和 最大流模板


    最大流

    Edmond-Karp

    原版的是用邻接矩阵写的,太耗内存了,这里改成邻接表。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N1 = 1e4 + 10, N2 = 2e5 + 10;
    const int INF = 0x3f3f3f3f;
    
    int head[N1], to[N2], nex[N2], cap[N2], cnt;
    int flow[N1], pre[N1], id[N1], n, m, s, t;
    
    void add(int x, int y, int w) {
        to[cnt] = y;
        nex[cnt] = head[x];
        cap[cnt] = w;
        head[x] = cnt++;
    }
    
    void input() {
        scanf("%d %d %d %d", &n, &m, &s, &t);
        int x, y, w;
        for(int i = 0; i < m; i++) {
            scanf("%d %d %d", &x, &y, &w);
            add(x, y, w);
            add(y, x, 0);
        }
    }
    
    void init() {
        memset(head, -1, sizeof head);
        cnt = 0;
    }
    
    int max_flow() {
        int ans = 0;
        for(;;) {
            queue<int> q;
            memset(flow, 0, sizeof flow);
            flow[s] = INF;
            q.push(s);
            while(!q.empty()) {
                int temp = q.front();
                q.pop();
                for(int i = head[temp]; ~i; i = nex[i]) {
                    if(!flow[to[i]] && cap[i] > 0) {
                        flow[to[i]] = min(flow[temp], cap[i]);
                        pre[to[i]] = temp;
                        id[to[i]] = i;
                        q.push(to[i]);
                    }
                }
                if(flow[t]) break;
            }
            if(!flow[t])    break;
            int p = t;
            while(p != s) {
                cap[id[p]] -= flow[t];
                cap[id[p] ^ 1] += flow[t];
                p = pre[p];
            }
            ans += flow[t];
        }
        return ans;
    }
    
    int main() {
        // freopen("in.txt", "r", stdin);
        init();
        input();
        printf("%d
    ", max_flow());
        return 0;
    }
    

    Dinic

    玄学的Dinic

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N1 = 1e4 + 10, N2 = 2e5 + 10;
    const int INF = 0x3f3f3f3f;
    
    int head[N1], to[N2], nex[N2], cap[N2], cnt;
    
    int dis[N1], n, m, s, t;
    
    void init() {
        memset(head, -1, sizeof head);
        cnt = 0;
    }
    
    void add(int x, int y, int w) {
        to[cnt] = y;
        nex[cnt] = head[x];
        cap[cnt] = w;
        head[x] = cnt++;
    }
    
    bool bfs() {
        memset(dis, -1, sizeof dis);
        queue<int> q;
        q.push(s);
        dis[s] = 0;
        while(!q.empty()) {
            int temp = q.front();
            q.pop();
            if(temp == t)   return true;
            for(int i = head[temp]; ~i; i = nex[i]) {
                if(dis[to[i]] == -1 && cap[i]) {
                    dis[to[i]] = dis[temp] + 1;
                    q.push(to[i]);
                }
            }
        }
        return false;
    }
    
    int dfs(int rt, int f) {
        if(rt == t) return f;
        int delta = f;
        for(int i = head[rt]; ~i; i = nex[i]) {
            if(dis[to[i]] == dis[rt] + 1) {
                int temp = dfs(to[i], min(delta, cap[i]));
                cap[i] -= temp;
                cap[i ^ 1] += temp;
                delta -= temp;
            }
            if(delta == 0)  break;
        } 
        return f - delta;
    }
    
    int Dinic() {
        int ans = 0;
        while(bfs()) ans += dfs(s, INF);
        return ans;
    }
    
    int main() {
        // freopen("in.txt", "r", stdin);
        init();
        scanf("%d %d %d %d", &n, &m, &s, &t);
        int x, y, w;
        for(int i = 0; i < m; i++) {
            scanf("%d %d %d", &x, &y, &w);
            add(x, y, w);
            add(y, x, 0);
        }
        printf("%d
    ", Dinic());
        return 0;
    }
    

    最小费用最大流

    SPFA

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N1 = 5e3 + 10, N2 = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    
    int head[N1], to[N2], nex[N2], cap[N2], value[N2], cnt;
    
    int dis[N1], pre[N1], id[N1], flow[N1], visit[N1], n, m, s, t;
    
    void add(int x, int y, int f, int w) {
        to[cnt] = y;
        nex[cnt] = head[x];
        value[cnt] = w;
        cap[cnt] = f;
        head[x] = cnt++;
    }
    
    bool spfa() {
        memset(visit, 0, sizeof visit);
        memset(dis, 0x3f, sizeof dis);
        queue<int> q;
        q.push(s);
        dis[s] = 0, visit[s] = 1, flow[s] = INF, pre[t] = -1;
        while(!q.empty()) {
            int temp = q.front();
            q.pop();
            visit[temp] = 0;
            for(int i = head[temp]; ~i; i = nex[i]) {
                if(cap[i] > 0 && dis[to[i]] > dis[temp] + value[i]) {
                    dis[to[i]] = dis[temp] + value[i];
                    flow[to[i]] = min(flow[temp], cap[i]);
                    pre[to[i]] = temp;
                    id[to[i]] = i;
                    if(!visit[to[i]]) {
                        q.push(to[i]);
                        visit[to[i]] = 1;
                    }
                }
            }
        }
        return  pre[t] != -1;
    }
    
    int min_cost_and_max_flow() {
        int max_flow = 0, min_cost = 0;
        while(spfa()) {
            max_flow += flow[t];
            min_cost += flow[t] * dis[t];
            int p = t;
            while(p != s) {
                cap[id[p]] -= flow[t];
                cap[id[p] ^ 1] += flow[t];
                p = pre[p];
            }
        }
        printf("%d %d
    ", max_flow, min_cost);
    }
    
    void init() {
        memset(head, -1, sizeof head);
        cnt = 0;
    }
    
    int main() {
        // freopen("in.txt", "r", stdin);
        init();
        scanf("%d %d %d %d", &n, &m, &s, &t);
        int x, y, f, w;
        for(int i = 0; i < m; i++) {
            scanf("%d %d %d %d", &x, &y, &f, &w);
            add(x, y, f, w);
            add(y, x, 0, -w);
        }
        min_cost_and_max_flow();
        return 0;
    }
    

    两个假的Dijkstra

    洛谷模板题卡爆DIjkstra。

    好像第一个稍优一点。

    第一个假的Dijkstra

    #include <bits/stdc++.h>
    #define mp make_pair
    #define pb push_back
    #define x first
    #define y second
    
    using namespace std;
    
    typedef pair<int, int> PII;
    const int N1 = 5e3 + 10;
    const int INF = 0x3f3f3f3f;
    
    int dis[N1], h[N1], flow[N1], pre[N1], id[N1], visit[N1], n, m, s, t;
    
    struct Edge {
        int to, cap, value, rever;
        Edge(int _to, int _cap, int _value, int _rever) : to(_to), cap(_cap), value(_value), rever(_rever) {}
    };
    
    vector<Edge> G[N1];
    
    void add(int x, int y, int f, int w) {
        Edge temp1 = Edge(y, f, w, G[y].size());
        Edge temp2 = Edge(x, 0, -w, G[x].size());
        G[x].pb(temp1);
        G[y].pb(temp2);
    }
    
    int min_cost_and_max_flow() {
        int min_cost = 0, max_flow = 0;
        memset(dis, 0x3f, sizeof dis);
        for(;;) {
            priority_queue<PII, vector<PII>, greater<PII> > q;
            dis[s] = 0, flow[s] = INF;
            q.push(mp(0, s));
            while(!q.empty()) {
                PII temp = q.top();
                q.pop();
                if(visit[temp.y])   continue;
                visit[temp.y] = 1;
                int u = temp.y;
                for(int i = 0; i < G[u].size(); i++) {
                    Edge v = G[u][i];
                    if(v.cap > 0 && dis[v.to] > dis[u] + v.value + h[u] - h[v.to]) {
                        dis[v.to] = dis[u] + v.value + h[u] - h[v.to];
                        flow[v.to] = min(v.cap, flow[u]);
                        pre[v.to] = u;
                        id[v.to] = i;
                        q.push(mp(dis[v.to], v.to));
                    }
                }
            }
            if(visit[t] == 0)    break;
            max_flow += flow[t];
            for(int i = 1; i <= n; i++) {
                h[i] += dis[i];
                dis[i] = INF;
                visit[i] = 0;
            }
            min_cost += flow[t] * h[t];
            int p = t;
            while(p != s) {
                G[pre[p]][id[p]].cap -= flow[t];
                G[p][ G[pre[p]][id[p]].rever].cap += flow[t];
                p = pre[p];
            }
        }
        printf("%d %d
    ", max_flow, min_cost);
    }
    
    int main() {
        // freopen("in.txt", "r", stdin);
        scanf("%d %d %d %d", &n, &m, &s, &t);
        int x, y, f, w;
        for(int i = 0; i < m; i++) {
            scanf("%d %d %d %d", &x, &y, &f, &w);
            add(x, y, f, w);
        }
        min_cost_and_max_flow();
        return 0;
    }
    

    第二个假的Dijkstra

    #include <bits/stdc++.h>
    #define mp make_pair
    
    using namespace std;
    
    typedef pair<int, int> PII;
    const int N1 = 5e3 + 10, N2 = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    
    int head[N1], to[N2], nex[N2], cap[N2], value[N2], cnt;
    
    int visit[N1], flow[N1], dis[N1], pre[N1], id[N1], h[N1], n, m, s, t;
    
    void init() {
        memset(head, -1, sizeof head);
        cnt = 0;
    }
    
    void add(int x, int y, int f, int w) {
        to[cnt] = y;
        nex[cnt] = head[x];
        value[cnt] = w;
        cap[cnt] = f;
        head[x] = cnt++;
    }
    
    int min_cost_and_max_flow() {
        int min_cost = 0, max_flow = 0;
        memset(dis, 0x3f, sizeof dis);
        for(;;) {
            priority_queue<PII, vector<PII>, greater<PII> > q;
            q.push(mp(0, s));
            flow[s] = INF, dis[s] = 0;
            while(!q.empty()) {
                int temp = q.top().second;
                q.pop();
                // if(temp == t)   break;
                if(visit[temp]) continue;
                visit[temp] = 1;
                // if(temp == t)   break;
                for(int i = head[temp]; ~i; i = nex[i]) {
                    if(cap[i] > 0 && dis[to[i]] > dis[temp] + value[i] + h[temp] - h[to[i]]) {
                        dis[to[i]] = dis[temp] + value[i] + h[temp] - h[to[i]];
                        flow[to[i]] = min(flow[temp], cap[i]);
                        pre[to[i]] = temp;
                        id[to[i]] = i;
                        q.push(mp(dis[to[i]], to[i]));
                    }
                }
            }
            if(visit[t] == 0)   break;
            for(int i = 1; i < n; i++) {
                h[i] += dis[i];
                visit[i] = 0;
                dis[i] = INF;
            }
            max_flow += flow[t];
            min_cost += flow[t] * h[t];
            int p = t;
            while(p != s) {
                cap[id[p]] -= flow[t];
                cap[id[p] ^ 1] += flow[t];
                p = pre[p];
            }
        }
        printf("%d %d
    ", max_flow, min_cost);  
    }
    
    
    int main() {
        // freopen("in.txt", "r", stdin);
        init();
        scanf("%d %d %d %d", &n, &m, &s, &t);
        int x, y, f, w;
        for(int i = 0; i < m; i++) {
            scanf("%d %d %d %d", &x, &y, &f, &w);
            add(x, y, f, w);
            add(y, x, 0, -w);
        }
        min_cost_and_max_flow();
        return 0;
    }
    
  • 相关阅读:
    三年Android开发经验,挥泪整理字节跳动、微软中国凉经,你不看看吗?
    App怎么做才能永不崩溃
    做了八年的Android开发,谁不是一边崩溃,一边默默坚守!
    阿里员工年年绩效A,晒出收入后感叹:996虽然痛苦,发钱时候真香
    2021阅读书单
    不动产测绘概念
    Elasticsearch 集成
    Elasticsearch 环境
    Elasticsearch 优化
    Elasticsearch入门
  • 原文地址:https://www.cnblogs.com/lifehappy/p/12901837.html
Copyright © 2020-2023  润新知