zoukankan      html  css  js  c++  java
  • 图结构模板

    #include<bits/stdc++.h>
    #define MAXN 100000
    #define D 10
    #define MAXM 10000010
    using std::cin;
    using std::cout;
    using std::endl;
    int m, n;//m为边数,n为点数
    //图的存储
    
    //邻接矩阵
    int a[5010][5010];
    void init() {
        cin >> n >> m;
        for (int i = 1; i <= m; i++) {
            int x, y;
            cin >> x >> y;
            a[x][y] = 1;
        }
    }
    
    //边表
    struct node {
        int x, y;
    } edge[MAXM + D];
    
    void init() {
        cin >> n >> m;
        for (int i = 1; i <= m; ++i)
            cin >> edge[i].x >> edge[i].y;
    }
    
    //前向星
    struct node {
        int x, y;
    } edge[500010];
    
    int st[MAXN + D], en[MAXN + D];
    
    inline bool cmp(node x, node y) {
        return x.x < y.y;
    }
    
    void init() {
        cin >> n >> m;
        for (int i = 1; i <= m; ++i) cin >> edge[i].x >> edge[i].y;
        std::sort(edge + 1, edge + 1 + m, cmp);
        st[edge[1].x] = 1;
        for (int i = 2; i <= m; ++i) {
            if (edge[i].x != edge[i - 1].x) en[edge[i - 1].x] = i - 1;
            st[edge[i].x] = i;
        }
        en[edge[m].x] = m;
    }
    
    //链表/链式前向星
    int lin[MAXN + D], len = 0;
    struct node {
        int y, ne;
    } edge[MAXM + D];
    
    inline void addedge(int x, int y) {
        edge[++len].y = y;
        edge[len].ne = lin[x];
        lin[x] = len;
    }
    
    void init() {
        cin >> n >> m;
        for (int i = 1; i <= m; ++i) {
            int x, y;
            cin >> x >> y;
            addedge(x, y);
        }
    }
    
    //图的遍历
    //DFS
    void dfs(int x) {
        vis[x] = true;
        for (int i = lin[x], y; i; i = edge[i].ne)
         if (!vis[y = edge[i].y]) dfs(y);
    }
    
    //DFS(邻接矩阵)
    void dfs(int x) {
        vis[x] = true;
        for (int i = 1; i <= n; ++i) if (a[x][i] && !vis[i]) dfs(i);
    }
    
    //BFS
    int head, tail, queue[MAXN + D];
    void bfs(int s) {
        vis[s] = true;
        head = 0, tail = 1;
        queue[1] = s;
        while (head++ < tail) {
            int x = queue[head];
            for (int i = lin[x], y; i; i = edge[i].ne)
             if (!vis[y = edge[i].y])
                  {
                    queue[++tail] = y;
                    vis[y] = true;
                }
        }
    }
    
    //BFS(邻接矩阵)
    int head, tail, queue[MAXN + D];
    void bfs(int s) {
        vis[s] = true;
        head = 0, tail = 1;
        queue[1] = s;
        while (head++ < tail) {
            int x = queue[head];
            for (int i = 1; i <= n; ++i) if (a[x][i] && !vis[i]) {
                    queue[++tail] = i;
                    vis[i] = true;
                }
        }
    }
    
    //最短路
    //Floyd
    void Floyd() {
        for (int k = 1; k <= n; ++k) for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) a[i][j] = std::min(a[i][j], a[i][k] + a[k][j]);
    }
    
    //Dijkstra
    #define INF 0x3f3f3f3f
    int dis[10010];
    int vis[10010];
    void Dijkstra(int s) {
        memset(vis, false, sizeof(vis));
        for (int i = 1; i <= n; i++) dis[i] = a[s][i];
        vis[s] = true;
        for (int i = 1; i < n; ++i) {
            int min = INF, x = 0;
            for (int i = 1; i <= n; ++i)
                if (!vis[i] && dis[i] < min) {
                    min = dis[i];
                    x = i;
                }
            if (!x) return;
            vis[x] = true;
            for (int i = 1; i <= n; ++i) dis[i] = std::min(dis[i], dis[x] + a[x][i]);
        }
    }
    
    //Dijkstra_with_priority_queue
    using std::pair;
    using std::priority_queue;
    using std::vector;
    using std::greater;
    using std::make_pair;
    #define INF 0x3f3f3f3f
    typedef pair<int, int> pii;
    pirority_queue<pii, vector<pii>, greater<pii> > queue;
    void Dijkstra(int s) {
        memset(dis, 0x3f, sizeof(dis));
        memset(vis, false, sizeof(vis));
        dis[s] = 0;
        queue.push(make_pair(dis[s], 0));
        while (!q.empty()) {
            pii tmp = q.top();
            q.pop();
            int x = tmp.second;
            if (vis[x]) continue;
            vis[x] = true;
            for (int i = lin[x], y; i; i = edge[i].ne) if (dis[y = edge[i].y] > dis[x] + edge[i].v) {
                    dis[y] = dis[x] + edge[i].v;
                    if (!vis[y]) q.push(make_pair(dis[y], y));
                }
        }
    }
    
    //Bellman-Ford
    void Bellman_Ford(int s) {
        memset(dis, 0x3f, sizeof(dis));
        dis[s] = 0;
        bool rel;
        for (int i = 1; i <= n; ++i) {
            rel = false;
            for (int j = 1; j <= len; ++j) if (dis[edge[j].y] > dis[edge[j].x] + edge[j].v)
                }
    }
    
    //SPFA
    int queue[10000010], head, tail;
    void SPFA(int s) {
        head = 0, tail = 1;
        memset(vis, false, sizeof(vis));
        memset(dis, 0x3f, sizeof(dis));
        dis[s] = 0;
        vis[s] = true;
        queue[1] = s;
        while (head++ < tail) {
            int x = queue[head];
            vis[x] = false;
            for (int i = lin[x], y; i; i = edge[i].ne) if (dis[y = edge[i].y] > dis[x] + edge[i].v) {
                    dis[y] = dis[x] + edge[i].v;
                    if (!vis[y]) {
                        vis[y] = true;
                        queue[++tail] = y;
                    }
                }
        }
    }
    
    //最小生成树
    //Prim
    #define INF 0x3f3f3f3f
    int Prim() {
        memset(vis, false, sizeof(vis));
        vis[1] = true;
        int sum = 0;
        for (int i = 1; i <= n; ++i) dis[i] = a[1][i];
        for (int i = 1; i < n; ++i) {
            int min = INF, x = 0;
            for (int j = 1; j <= n; ++j) if (!vis[j] && dis[j] < min) {
                    min = dis[j];
                    x = j;
                }
            vis[x] = true;
            sum += min;
            for (int j = 1; j <= n; ++j) dis[j] = std::min(dis[j], a[x][j]);
        }
        return sum;
    }
    
    //Kruskal
    struct node {
        int x, y, v;
    } edge[100010];
    
    inline bool cmp(node x, node y) {
        return x.v <y.v;
    }
    
    int father[MAXN + D];
    
    int getfather(int x) {
        return (father[x] == x) ? x : (father[x] = getfather(father[x]));
    }
    
    int Kruskal() {
        for (int i = 1; i <= n; ++i) father[i] = i;
        int sum = 0, cnt = 0;
        std::sort(edge + 1, edge + 1 + m, cmp);
        for (int i = 1; i <= m && cnt < n - 1; ++i) {
            int x = getfather(edge[i].x), y = getfather(edge[i].y);
            if (x != y) {
                ++cnt;
                sum += edge[i].v;
                father[x] = y;
            }
        }
        return sum;
    }
    
    //拓扑排序
    int queue[MAXN + D], head, tail, in_degree[MAXN + D], ans[100][MAXN + D], tot = 0;
    
    void init() {
        cin >> n >> m;
        for (int i = 1; i <= m; ++i) {
            int x, y;
            cin >> x >> y;
            addedge(x, y);
            ++in_degree[y];
        }
    }
    
    //BFS
    void bfs() {
        head = 0, tail = 0;
        for (int i = 1; i <= n; ++i) if (!in_degree[i]) queue[++tail] = y;
        while (head++ < tail) {
            int x = queue[head];
            for (int i = lin[x],y; i; i = edge[i].ne) if (!(--in_degree[y = edge[i].y])) queue[++tail] = y;
        }
    }
    
    //DFS
    void dfs(int x, int dep) {
        queue[dep] = x;
        vis[x] = true;
        if (dep == n) {
            ++tot;
            for (int i = 1; i <= n; ++i) ans[tot][i] = queue[i];
            vis[x] = false;
        }
        for (int i = lin[x]; i; i = edge[i].ne) --in_degree[edge[i].y];
        for (int i = 1; i <= n; ++i) if (!vis[i] && !in_degree[i]) dfs(i, dep + 1);
        for (int i = lin[x]; i; i = edge[i].ne) ++in_degree[edge[i].y];
        vis[x] = false;
    }
    
    //Tarjan
    //割点
    int dfn[MAXN + D], low[MAXN + D], _clock = 0;
    bool iscut[MAXN + D]
    void tarjan(int x, int par = 0) {
        int child = 0;
        dfn[x] = low[x] = ++_clock;
        for (int i = lin[x], y; i; i = edge[i].ne) {
            if ((y = edge[i].y) == par) continue;
            if (!dfn[y]) {
                tarjan(y, x);
                if (low[y] < low[x]) low[x] = low[y];
                else if (low[y] >= dfn[x]) ++child;
            } else if (dfn[y] < low[x]) low[x] = dfn[y];
        }
        if (child >= 2 || (child == 1 && par)) iscut[x] = true;
    }
    
    int main() {
        for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i);
    }
    
    //点双连通分量
    using std::vector;
    vector<int> bcc[MAXN + D];
    int size[MAXN + D], dfn[MAXN + D], low[MAXN + D], _clock = 0, bel[MAXN + D], stack[MAXM + D], top = 0;
    void tarjan(int x, int par = 0) {
        int child = 0;
        dfn[x] = low[x] = ++_clock;
        for (int i = lin[x], y; i; i = edge[i].ne) {
            if ((y = edge[i].y) == par) continue;
            if (!dfn[y]) {
                stack[++top] = i;
                tarjan(y, x);
                if (low[y] < low[x]) low[x] = low[y];
                else if (low[y] >= dfn[x]) {
                    ++child;
                    int k;
                    ++tot;
                    do {
                        k = stack[top--];
                        if (bel[edge[k].x] != tot) {
                            bel[edge[k].x] = tot;
                            bcc[tot].push_back(edge[k].x);
                            ++size[tot];
                        }
                        if (bel[edge[k].y] != tot) {
                            bel[edge[k].y] = tot;
                            bcc[tot].push_back(edge[k].y);
                            ++size[tot];
                        }
                    } while (k != i);
                }
            } else if (dfn[y] < low[x]) {
                low[x] = dfn[y];
                stack[++top] = i;
            }
        }
        if (child >= 2 || (par && child)) iscut[x] = true;
    }
    
    int main() {
        for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i);
    }
    
    //割边
    int dfn[MAXN + D], low[MAXN + D], _clock = 0, rev[(MAXM << 1) + D];
    bool isbridge[(MAXM << 1) + d];
    void tarjan(int x, int par = 0) {
        dfn[x] = low[x] = ++_clock;
        for (int i = lin[x], y; i; i = edge[i].ne) {
            if (i == par) continue;
            if (!dfn[y = edge[i].y]) {
                tarjan(y, rev[i]);
                if (low[y] < low[x]) low[x] = low[y];
            } else if (dfn[y] < low[x]) low[x] = dfn[y];
        }
        if (dfn[x] == low[x]) isbridge[par] = isbridge[rev[par]] = true;
    }
    
    int main() {
        for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i);
    }
    
    //求割边后求边双连通分量
    int tot = 0, bel[MAXN + D], size[MAXN + D];
    void dfs(int i) {
        bel[i] = tot;
        ++size[tot];
        for (int i = lin[x], y; i; i = edge[i].ne) {
            if (isbridge[i] || bel[y = edge[i].y]) continue;
            dfs(y);
        }
    }
    
    int main() {
        for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i);
        for (int i = 1; i <= n; ++i) if (!bel[i]) {
                ++tot;
                dfs(i);
            }
    }
    
    //连通分量
    int dfn[MAXN + D], low[MAXN + D], _clock = 0, top = 0, stack[MAXN + D], bel[MAXN + D], size[MAXN + D], tot;
    bool vis[MAXN + D];
    void tarjan(int x) {
        vis[x] = true;
        stack[++top] = x;
        dfn[x] = low[x] = ++_clock;
        for (int i = lin[x], y; i; i = edge[i].ne) {
            if (!dfn[y = edge[i].y]) {
                tarjan(y);
                if (low[y] < low[x]) low[x] = low[y];
            } else if (vis[y] && dfn[y] < low[x]) low[x] = dfn[y];
        }
        if (dfn[x] == low[x]) {
            int k;
            tot++;
            do {
                k = stack[top--];
                vis[k] = false;
                ++size[tot];
                bel[k] = tot;
            } while (k != x);
        }
    }
    
    int main() {
        for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i);
    }
    
    //DFS序列化
    int st[MAXN + D], en[MAXN + D], _clock = 0;
    void dfs(int x, int par = 0) {
        st[x] = ++_clock;
        for (int i = lin[x], y; i; i = edge[i].ne) if ((y = edge[i].y) != par) dfs(y, x);
        en[x] = _clock;
    }
    
    //轻重链剖分
    int st[MAXN + D], en[MAXN + D], _clock = 0, top[MAXN + D], size[MAXN + D], son[MAXN + D], father[MAXN + D], depth[MAXN + D];
    void find_heavy_edge(int x, int par = 0) {
        father[x] = par;
        depth[x] = depth[par] + 1;
        size[x] = 1;
        int maxsize = 0;
        son[x] = 0;
        for (int i = lin[x], y; i; i = edge[i].y) {
            if ((y = edge[i].y) == par) continue;
            find_heavy_edge(y, x);
            if (size[y] > maxsize) {
                maxsize = size[y];
                son[x] = y;
            }
            size[x] += size[y];
        }
    }
    
    void connect_heavy_edge(int x, int par) {
        st[x] = ++_clock;
        top[x] = par;
        if (son[x]) connect_heavy_edge(son[x], par);
        for (int i = lin[x], y; i; i = edge[i].ne) {
            y = edge[i].y;
            if (y == par || y == son[x]) continue;
            connect_heavy_edge(y, y);
        }
        en[x] = _clock;
    }
    
    int main() {
        find_heavy_edge(1);
        connect_heavy_edge(1, 1);
    }
    
    //LCA
    //树链剖分
    int LCA(int u, int v) {
        while (top[u] != top[v]) {
            if (depth[top[u]] < depth[top[v]]) std::swap(u, v);
            u = father[top[u]];
        }
        if (depth[u] > depth[v]) std::swap(u, v);
        return v;
    }
    
    //倍增法
    int father[MAXN + D][20], depth[MAXN + D], M;
    void dfs(int x) {
        for (int i = 1; (1 << i) <= n && father[x][i - 1]; ++i) father[x][i] = father[father[x][i - 1]][i - 1];
        for (int i = lin[x], y; i; i = edge[i].ne) {
            if ((y = edge[i].y) == father[x][0]) continue;
            father[y][0] = x;
            dfs(y);
        }
    }
    
    int LCA(int u, int v) {
        if (depth[u] < depth[v]) std::swap(u, v);
        for (int i = 0; depth[u] != depth[v]; ++i) if ((1 << i) & (depth[u] - depth[v])) u = father[u][i];
        if (u == v) return u;
        for (int i = M; i >= 0; --i) if (father[u][i] != father[v][i]) {
                u = father[u][i];
                v = father[v][i];
            }
        return father[u][0];
    }
    
    int main() {
        for (M = 0; (1 << M) <= n; ++M);
        --M;
        dfs(1);
    }
    
    //tarjan离线法
    struct query {
        int y, ne, id;
    } query[MAXM + D];
    
    int len_query = 0, lin_query[MAXN + D], father[MAXN + D], ans[MAXM + D];
    bool vis[MAXN + D];
    inline void addquery(int x, int y, int id) {
        query[++len_query].y = y;
        query[len_query].ne = lin_query[x];
        lin_query[x] = len_query;
        query[len_query].id = id;
    }
    
    int getfather(int x) {
        return (father[x] == x) ? x : (father[x] = getfather(father[x]));
    }
    
    void tarjan(int x, int par = 0) {
        for (int i = lin[x], y; i; i = edge[i].ne) {
            if ((y = edge[i].y) == par) continue;
            tarjan(y, x);
            father[y] = x;
            vis[y] = true;
        }
        for (int i = lin_query[x], y; i; i = query[i].ne) {
            if (!vis[y = query[i].y]) continue;
            ans[query[i].id] = getfather(y);
        }
    }
    
    int main() {
        for (int i = 1; i <= n; ++i) father[i] = i;
        tarjan(1);
    }
    
    //点分治
    int size[MAXN + D], root, sum = 0, maxsize[MAXN + D];
    bool vis[MAXN + D];
    void getroot(int x, int par) {
        size[x] = 1;
        maxsize[x] = 0;
        for (int i = lin[x], y; i; i = edge[i].ne) {
            y = edge[i].y;
            if (y == par || vis[y]) continue;
            getroot(y, x);
            maxsize[x] = std::max(maxsize[x], size[y]);
            size[x] += size[y];
        }
        maxsize[x] = std::max(maxsize[x], sum - maxsize[x]);
        if (maxsize[x] < maxsize[root]) root = x;
    }
    
    void cal(int x, int par) {
    //计算当前点贡献
        for (int i = lin[x], y; i; i = edge[i].ne) {
            y = edge[i].y;
            if (vis[y] || y == par) continue;
            cal(y, x);
        }
    }
    
    void add(int x, int par, bool opt) {
        if (opt) {
    //将当前点加入到计算的点中
        } else {
    //将当前点从已计算的点集删除
        }
        for (int i = lin[x], y; i; i = edge[i].ne) {
            y = edge[i].y;
            if (vis[y] || y == par) continue;
            add(y, x, opt);
        }
    }
    
    void solve(int x) {
        getroot(x);
        vis[x] = true;
        for (int i = lin[x], y; i; i = edge[i].ne) {
            y = edge[i].y;
            if (vis[y]) continue;
            cal(y, x);
            add(y, x, true);
        }
        for (int i = lin[x], y; i; i = edge[i].ne) {
            y = edge[i].y;
            if (vis[y]) continue;
            add(y, x, false);
        }
        for (int i = lin[x], y; i; i = edge[i].ne) {
            y = edge[i].y;
            if (vis[y]) continue;
            sum = size[y];
            root = 0;
            getroot(y, x);
            solve(root);
        }
    }

    大量图结构模板,可能会有帮助...

  • 相关阅读:
    安装jdk1.8导致eclipse显示问题
    Linux创建定时任务
    Burp suite抓取HTTPS请求
    Webbench性能测试
    Fiddler抓取手机Https请求
    Linux下使用Jmeter做性能测试
    Charles抓取手机https请求
    Jmeter发送Java请求
    Linux搭建JDK、Tomcat安装及配置
    Loadrunner监控Apache
  • 原文地址:https://www.cnblogs.com/AK-ls/p/10107699.html
Copyright © 2011-2022 走看看