zoukankan      html  css  js  c++  java
  • [kuangbin带你飞]专题十一 网络流

    const int maxn = 1e4 + 5;
    const int maxm = 2e5 + 5;
    struct Edge {
        int from, to, next , cap;
    } edge[maxm];
    int head[maxn];
    int tol;
    int s, t;
    void init() {
        ms(head, -1);
        tol = 0;
    }
    void add(int u, int v, int w) {
        edge[tol].from = u;
        edge[tol].to = v;
        edge[tol].cap = w;
        edge[tol].next = head[u];
        head[u] = tol++;
    
        edge[tol].from = v;
        edge[tol].to = u;
        edge[tol].cap = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }
    int dep[maxn];
    int gap[maxn];
    int q[maxn];
    void bfs() {
        ms(dep, -1);
        ms(gap, 0);
        dep[t] = 0;
        gap[0] = 1;
        int l = 0, r = 0;
        q[r++] = t;
        while(l < r) {
            int u = q[l++];
            for(int i = head[u]; i != -1; i = edge[i].next) {
                int v = edge[i].to;
                int w = edge[i^1].cap;
                if(w != 0 && dep[v] == -1) {
                    ++gap[dep[v] = dep[u] + 1];
                    q[r++] = v;
                }
            }
        }
    }
    int cur[maxn], stk[maxn];
    int sap(int n) {
        int res = 0;
        int top = 0;
        bfs();
        memcpy(cur, head, sizeof(head));
        int u = s, i;
        while(dep[s] < n) {
            if(u == t) {
                int Min = inf;
                int tn = n;
                for(i = 0; i < top; i++) {
                    if(Min > edge[stk[i]].cap) {
                        Min = edge[stk[i]].cap;
                        tn = i;
                    }
                }
                for(i = 0; i < top; i++) {
                    edge[stk[i]].cap -= Min;
                    edge[stk[i] ^ 1].cap += Min;
                }
                res  += Min;
                top = tn;
                u = edge[stk[tn]].from;
            }
    
            for(i = cur[u]; i != -1; i = edge[i].next) if(edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)break;
    
            if(i != -1) {
                cur[u] = i;
                stk[top++] = i;
                u = edge[i].to;
            } else {
                if(--gap[dep[u]] == 0)break;
                int minn = n;
                for(i = head[u]; i != -1; i = edge[i].next) {
                    if(edge[i].cap && minn > dep[edge[i].to]) {
                        minn = dep[edge[i].to];
                        cur[u] = i;
                    }
                }
                ++gap[dep[u] = minn + 1];
                if(u != s) {
                    u = edge[stk[--top]].from;
                }
            }
        }
        return res;
    }
    isap

    B - Dining

    题意比较简单,有N头牛,农场主人准备了(1 - F)F份食物和,(1 - D)D份饮料,每头牛i有自己喜欢的fi份食物和di份饮料,ai1... aif, bi1 ... bid,问你最多有几头牛能得到自己喜欢的食物和饮料

    水题。建一个源点0连接所有食物i,(标号为2 * N + i) ,把全部饮料i(标号为2 * N  + F + i)连接汇点(标号N * 2+ F + D + 1),然后把每头牛i拆成两个点i,i+N,连上一条容量为1的边,再把牛i和喜欢的食物连接起来,食物 - > 牛i,再把牛i和饮料连接起来,牛i + N - > 饮料.跑一下最大流就得出答案了。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <queue>
    #include <vector>
    #include <time.h>
    #include <string>
    #include <stack>
    #include <set>
    #include <map>
    #include <iostream>
    #include <bitset>
    #include <algorithm>
    using namespace std;
    #define MP make_pair
    #define PB push_back
    #define ms(a,b) memset((a),(b),sizeof(a))
    typedef long long LL;
    typedef pair<int, int> Pii;
    typedef vector<int> Vi;
    typedef vector<Pii> Vii;
    const int inf = 0x3f3f3f3f;
    const LL INF = (1uLL << 63) - 1;
    const LL mod = 1000000007;
    const double Pi = acos(-1.0);
    const int maxn = 1e4 + 5;
    const int maxm = 2e5 + 5;
    struct Edge {
        int from, to, next , cap;
    } edge[maxm];
    int head[maxn];
    int tol;
    int s, t;
    void init() {
        ms(head, -1);
        tol = 0;
    }
    void add(int u, int v, int w) {
        edge[tol].from = u;
        edge[tol].to = v;
        edge[tol].cap = w;
        edge[tol].next = head[u];
        head[u] = tol++;
    
        edge[tol].from = v;
        edge[tol].to = u;
        edge[tol].cap = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }
    int dep[maxn];
    int gap[maxn];
    int q[maxn];
    void bfs() {
        ms(dep, -1);
        ms(gap, 0);
        dep[t] = 0;
        gap[0] = 1;
        int l = 0, r = 0;
        q[r++] = t;
        while(l < r) {
            int u = q[l++];
            for(int i = head[u]; i != -1; i = edge[i].next) {
                int v = edge[i].to;
                int w = edge[i^1].cap;
                if(w != 0 && dep[v] == -1) {
                    ++gap[dep[v] = dep[u] + 1];
                    q[r++] = v;
                }
            }
        }
    }
    int cur[maxn], stk[maxn];
    int sap(int n) {
        int res = 0;
        int top = 0;
        bfs();
        memcpy(cur, head, sizeof(head));
        int u = s, i;
        while(dep[s] < n) {
            if(u == t) {
                int Min = inf;
                int tn = n;
                for(i = 0; i < top; i++) {
                    if(Min > edge[stk[i]].cap) {
                        Min = edge[stk[i]].cap;
                        tn = i;
                    }
                }
                for(i = 0; i < top; i++) {
                    edge[stk[i]].cap -= Min;
                    edge[stk[i] ^ 1].cap += Min;
                }
                res  += Min;
                top = tn;
                u = edge[stk[tn]].from;
            }
    
            for(i = cur[u]; i != -1; i = edge[i].next) if(edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)break;
    
            if(i != -1) {
                cur[u] = i;
                stk[top++] = i;
                u = edge[i].to;
            } else {
                if(--gap[dep[u]] == 0)break;
                int minn = n;
                for(i = head[u]; i != -1; i = edge[i].next) {
                    if(edge[i].cap && minn > dep[edge[i].to]) {
                        minn = dep[edge[i].to];
                        cur[u] = i;
                    }
                }
                ++gap[dep[u] = minn + 1];
                if(u != s) {
                    u = edge[stk[--top]].from;
                }
            }
        }
        return res;
    }
    int main() {
    #ifdef local
        freopen("in", "r", stdin);
        //  freopen("w","w",stdout);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0);
        init();
        int N, F, D , x;
        cin >> N >> F >> D;
        s = 0, t = N + N + F + D + 1;
        for(int i = 1; i <= F; i++) {
            add(0, i + 2 * N, 1);
        }
        for(int i = 1; i <= N; i++) {
            int f, d;
            add(i, i + N, 1);
            cin >> f >> d;
            for(int j = 0; j < f; j++) {
                cin >> x;
                add(x + 2 * N, i, 1);
            }
            for(int j = 0; j < d; j++) {
                cin >> x;
                add(i + N, x + 2 * N + F, 1);
            }
        }
        for(int i = 1; i <= D; i++) {
            add(i + 2 * N + F, t, 1);
        }
        cout << sap(t + 1) << endl;
    }
    View Code
  • 相关阅读:
    C语言 strcat
    C语言 strncpy
    C语言 strcpy
    C语言 main
    可显示Android设备选择列表,并进入指定Android设备Console的Shell脚本
    Android系统如何录制屏幕(录制成mp4格式)
    据说有99%的人都会做错的面试题
    一道淘汰85%面试者的百度开发者面试题
    用Android模拟器也可以开发和测试NFC应用
    一道腾讯面试题的思考:到底谁会赢?
  • 原文地址:https://www.cnblogs.com/scau-zk/p/6492404.html
Copyright © 2011-2022 走看看