【模板】图

时间:2020-04-09 13:02:23   收藏:0   阅读:68

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;
}

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!