zoukankan      html  css  js  c++  java
  • 【模板】图

    1 双向邻接表

    inline void addedge(int u, int v) {
        to[++E] = v, next[E] = first[u], first[u] = E;
        to[++E] = u, next[E] = first[v], first[v] = E;
    }

    2 有向图的强连通分量

    void dfs(int x) {
        int i, y;
        id[x] = low[x] = ++cnt; instack[x] = 1; sta[stc++] = x;
        for(i = first[x]; i; i = next[i])
            if (!id[y = to[i]])
                dfs(y), down(low[x], low[y]);
            else if (instack[y])
                down(low[x], id[y]);
        if (id[x] == low[x])
            for (y = 0; y != x; )
                y = sta[--stc], instack[y] = 0, top[y] = x;
    }

    3 有向无环图的拓扑排序

    void Toposort(){
        int h, t = 0, x, y, i;
        for (i = 1; i <= V; ++i) if (!deg[i]) que[t++] = i;
        for (h = 0; h < t; ++h)
            for (i = first[x = que[h]]; i; i = next[i])
                if (!--deg[y = to[i]]) que[t++] = y;
    }

    4 无向图的桥边

    void dfs(int x, int px = 0) {
        int i, y;
        id[x] = low[x] = ++cnt;
        for (i = first[x]; i; i = next[i])
            if (!id[y = to[i]]){
                dfs(y, i), down(low[x], low[y]);
                if (id[x] < low[y]) // edge i is a bridge
            } else if (px - 1 ^ i - 1 ^ 1)
                down(low[x], id[y]);
    }

    5 无向图的割点

    void dfs(int x, int px = 0) {
        int i, y, c = 0; bool is_cut;
        id[x] = low[x] = ++cnt;
        for (i = first[x]; i; i = next[i])
            if (!id[y = to[i]]) {
                dfs(y, i), down(low[x], low[y]), ++c;
                if (id[x] <= low[y]) is_cut = true;
            } else if (px - 1 ^ i - 1 ^ 1)
                down(low[x], id[y]);
        is_cut |= !px && c > 1;
    }

    6 无向图的边双缩点

    void dfs(int x, int px = 0) {
        int i, y;
        id[x] = low[x] = ++cnt, stack[stc++] = x;
        for (i = first[x]; i; i = next[i])
            if (!id[y = to[i]]) {
                dfs(y, i), down(low[x], low[y]);
                if (id[x] < low[y]) bridge[ad(i)] = bridge[i] = true;
            } else if (px - 1 ^ i - 1 ^ 1)
                down(low[x], id[y]);
        if (id[x] == low[x])
            for (y = 0; y != x; )
                y = stack[--stc], top[y] = x;
    }

    7 无向图的点双缩点 / 圆方树

    void dfs(int x, int px = 0) {
        int i, y, z;
        id[x] = low[x] = ++cnt, stack[top++] = x;
        for (i = first[x]; i; i = next[i])
            if (!id[y = to[i]]) {
                dfs(y, i), down(low[x], low[y]);
                if (id[x] <= low[y])
                    for (link(++bcc_cnt + V, x), z = 0; z != y; )
                        link(z = stack[--top], bcc_cnt + V);
            } else if (px - 1 ^ i - 1 ^ 1)
                down(low[x], id[y]);
    }

    8 带权 edge 结构体

    struct edge {
        int u, v, w;
        edge (int u0 = 0, int v0 = 0, int w0 = 0) : u(u0), v(v0), w(w0) {}
    };

    9 单源最短路 (Dijkstra)

    #include <ext/pb_ds/priority_queue.hpp>
    using __gnu_pbds::priority_queue;
    
    struct node{
        int to, dist;
        node (int to0 = 0, int dist0 = 0): to(to0), dist(dist0) {}
        inline bool operator < (const node &b) const {return dist > b.dist;}
    };
    
    priority_queue <node> pq;
    
    void Dijkstra(int s){
        int i, y; node t;
        for(i = 1; i <= V; i++) d[i] = (i == s ? 0 : INF);
        for(pq.push(node(s, 0)); !pq.empty(); ){
            t = pq.top(); pq.pop();
            if(d[t.to] < t.dist) continue;
            for(i = first[t.to]; i; i = next[i])
                if(t.dist + e[i].w < d[y = e[i].v]){
                    d[y] = t.dist + e[i].w;
                    pq.push(node(y, d[y]));
                }
        }
    }

    10 所有点对的最短路 (Floyd)

    int Floyd(){
        int i, j, k;
        for(k = 1; k <= V; k++)
            for(i = 1; i <= V; i++)
                for(j = 1; j <= V; j++)
                    down(d[i][j], d[i][k] + d[k][j]);
        return 0;
    }

    11 最小生成树 (Kruskal)

    struct edge{
        int u, v, w;
        edge (int u0 = 0, int v0 = 0, int w0 = 0): u(u0), v(v0), w(w0) {}
        bool operator < (const edge &b) const {return w < b.w;}
    };
    
    void Kruskal(){
        uf.resize(V);
        sort(e + 1, e + (E + 1));
        for(i = 1; i <= E; i++)
            if(!uf.test(e[i].u, e[i].v, true)){
                // e is an edge of minimum spanning tree
                if(++Es >= V - 1) return;
            }
    }

    12 网络流 edge 结构体

    struct edge{
        int u, v, f; // f is remaining flow
        edge(int u0 = 0, int v0 = 0, int f0 = 0): u(u0), v(v0), f(f0) {}
    };

    13 最大流 (Dinic)

    namespace Flow {
        #define ad(x) ((x - 1 ^ 1) + 1)
    
        const int N = 2000, M = 100000;
    
        struct edge {
            int u, v, f;
            edge (int u0 = 0, int v0 = 0, int f0 = 0) : u(u0), v(v0), f(f0) {}
        } e[M];
    
        int V = 2, E = 0, si = 1, ti = 2, flow;
        int first[N], next[M];
        int dep[N], cur[N], que[N];
    
        inline void addedge(int u, int v, int f) {
            e[++E] = edge(u, v, f), next[E] = first[u], first[u] = E;
            e[++E] = edge(v, u), next[E] = first[v], first[v] = E;
        }
    
        bool bfs() {
            int h, t = 1, i, x, y;
            memset(dep, -1, sizeof dep);
            que[0] = si, dep[si] = 0;
            for (h = 0; h < t; h++) {
                if ((x = que[h]) == ti) return true;
                for (i = first[x]; i; i = next[i])
                    if (dep[y = e[i].v] == -1 && e[i].f)
                        que[t++] = y, dep[y] = dep[x] + 1;
            }
            return false;
        }
    
        int dfs(int x, int lim) {
            int a, c, f = 0;
            if (x == ti || !lim) return lim;
            for (int &i = cur[x]; i; i = next[i])
                if (dep[e[i].v] == dep[x] + 1 && e[i].f) {
                    a = std::min(lim - f, e[i].f);
                    c = dfs(e[i].v, a);
                    e[i].f -= c; e[ad(i)].f += c;
                    if ((f += c) == lim) return f;
                }
            return f;
        }
    
        int Dinic() {
            for (flow = 0; bfs(); flow += dfs(si, INT_MAX))
                memcpy(cur, first, sizeof cur);
            return flow;
        }
    }

    14 最小费用最大流 (Dinic)

    namespace CF {
        #define ad(x) ((x - 1 ^ 1) + 1)
    
        const int N = 2000, M = 100000, INF = 0x7f7f7f7f;
    
        struct edge {
            int u, v, c, f;
            edge (int u0 = 0, int v0 = 0, int c0 = 0, int f0 = 0) : u(u0), v(v0), c(c0), f(f0) {}
        } e[M];
    
        int V = 2, E = 0, si = 1, ti = 2, flow, cost;
        int first[N], next[M];
        int dep[N], cur[N], que[M << 1];
        bool in_que[N], used[N];
    
        inline void addedge(int u, int v, int c, int f) {
            e[++E] = edge(u, v, c, f), next[E] = first[u], first[u] = E;
            e[++E] = edge(v, u, -c), next[E] = first[v], first[v] = E;
        }
    
        bool bfs() {
            int h = M, t = h + 1, i, x, y;
            memset(dep, 127, sizeof dep);
            que[h] = ti, dep[ti] = 0, in_que[ti] = true;
            for (; h < t; ) {
                x = que[h++], in_que[x] = false;
                for (i = first[x]; i; i = next[i])
                    if (dep[y = e[i].v] > dep[x] - e[i].c && e[ad(i)].f) {
                        dep[y] = dep[x] - e[i].c;
                        if (!in_que[y])
                            in_que[y] = true, (dep[y] >= dep[que[h]] ? que[t++] : que[--h]) = y;
                    }
            }
            return dep[si] < INF;
        }
    
        int dfs(int x, int lim) {
            int a, c, f = 0;
            if (x == ti || !lim) return lim;
            used[x] = true;
            for (int &i = cur[x]; i; i = next[i])
                if (dep[e[i].v] == dep[x] - e[i].c && e[i].f && !used[e[i].v]) {
                    a = std::min(lim - f, e[i].f);
                    c = dfs(e[i].v, a);
                    e[i].f -= c, e[ad(i)].f += c;
                    if ((f += c) == lim) return f;
                }
            return f;
        }
    
        int Dinic() {
            int f;
            for (cost = flow = 0; bfs(); ) {
                memcpy(cur, first, sizeof cur);
                memset(used, 0, sizeof used);
                flow += f = dfs(si, INF);
                cost += dep[si] * f;
            }
            return cost;
        }
    }

    15 二分图最大匹配 (增广路算法)

    bool dfs(int x){
        for(int i = 1; i <= n_g; i++)
            if(e[x][i] && !used[i]){
                used[i] = 1;
                if(!boy[i] || dfs(boy[i])){
                    boy[i] = x; girl[x] = i; return true;
                }
            }
        return false;
    }

    16 一般图最大匹配 (带花树算法)

    #define unknown -1
    #define boy 0
    #define girl 1
    
    int LCA(int x, int y) {
        for (++hash_cnt; x; y ? swap(x, y) : (void)0) {
            x = ancestor(x);
            if (hash[x] == hash_cnt) return x; // visited
            hash[x] = hash_cnt;
            x = prev[match[x]];
        }
        return 0x131a371;
    }
    
    void blossom(int x, int y, int root, int &t) { // vertices in blossoms are all boys !
        for (int z; ancestor(x) != root; y = z, x = prev[y]) {
            prev[x] = y; z = match[x];
            if (col[z] == girl) que[t++] = z, col[z] = boy;
            if (ancestor(x) == x) p[x] = root;
            if (ancestor(z) == z) p[z] = root;
        }
    }
    
    bool bfs(int st) {
        int h, t = 1, i, x, y, b, g;
        que[0] = st; col[st] = boy;
        for (h = 0; h < t; ++h)
            for (i = first[x = que[h]]; i; i = next[i])
                if (col[y = to[i]] == unknown) { // common step
                    prev[y] = x; col[y] = girl;
                    if (!match[y]) { // augment (change mates) !!!
                        for (g = y; g; swap(match[b], g))
                            match[g] = b = prev[g];
                        return true;
                    }
                    col[que[t++] = match[y]] = boy;
                } else if(col[y] == boy && ancestor(x) != ancestor(y)) { // flower !!!
                    b = LCA(x, y); blossom(x, y, b, t); blossom(y, x, b, t);
                }
        return false;
    }
    
    // main process
    for (i = 1; i <= V; ++i) {
        for (v = 1; v <= V; ++v) col[v] = unknown, p[v] = v;
        if (!match[i] && bfs(i)) ++ans;
    }
  • 相关阅读:
    jQuery笔记(1)
    [bzoj 1878][SDOI2009]HH的项链
    [bzoj 1968][Ahoi2005]COMMON 约数研究
    [bzoj 1899][ZJOI2004]lunch 午餐
    [bzoj 1090][SCOI2003]字符串折叠
    CodeForces 1029E div3
    [bzoj 1270][BeijingWc2008]雷涛的小猫
    [bzoj 1260][CQOI 2007]涂色paint
    [AtCoder ARC101D/ABC107D] Median of Medians
    [luogu 1070]道路游戏(NOIP2009T4)
  • 原文地址:https://www.cnblogs.com/lau1997/p/12665798.html
Copyright © 2011-2022 走看看