zoukankan      html  css  js  c++  java
  • 有向图强连通分量

    给你一个有向图,然后问你,加入多少条边,能使这个图构成成一个强连通分量

    首先,把强连通分量缩成一个点,然后现在就成了一个dag,这个dag中 看只有入度 和只有出度的点 取max就好了

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <stack>
    #include <vector>
    #include <map>
    #include <algorithm>
    using namespace std;
    
    const int MaxN = 50000, MaxM = 200000;
    
    int T, n, m, all, Timetot, Scctot; 
    int pre[MaxM + 5], last[MaxN + 5], other[MaxM + 5];
    int pr[MaxM + 5], las[MaxN + 5], oth[MaxM + 5];
    int dfn[MaxN + 5], low[MaxN + 5], col[MaxN + 5];
    int ind[MaxN + 5], oud[MaxN + 5];
    bool usedind[MaxN + 5], usedoud[MaxN + 5], usedused[MaxN + 5];
    stack <int> sta;
    vector <int> Scc[MaxN + 5];
    map <pair<int, int>, bool> used;
    
    void Build(int x, int y)
    {
        pre[++all] = last[x];
        last[x] = all;
        other[all] = y;
    }
    
    void Init()
    {
        all = -1; memset(last, -1, sizeof(last));
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            Build(u, v); 
        }
    }
    
    void Dfs_Scc(int x, int fa)
    {
        dfn[x] = low[x] = ++Timetot;
        sta.push(x);    //强连通分量 存点不存边
        int ed = last[x], dr;
        while (ed != -1) {
            dr = other[ed];
            if (!dfn[dr]) {
                Dfs_Scc(dr, x);
                low[x] = min(low[x], low[dr]);
            }
            else if (!col[dr] && dfn[dr] < dfn[x]) {
                low[x] = min(low[x], dfn[dr]);
            }
            ed = pre[ed];
        }
        if (low[x] >= dfn[x]) { //强连通分量注意是while出来以后判
            Scc[++Scctot].clear();
            while (true) {
                int u = sta.top(); sta.pop();
                col[u] = Scctot;
                Scc[Scctot].push_back(u);
                if (u == x) break;
            }
        }
    }
    
    void rBuild(int x, int y)
    {
        pr[++all] = las[x];
        las[x] = all;
        oth[all] = y;
        ind[x]++;
        oud[y]++;
    }
    
    void ReBuildGraph()
    {
        used.clear();
        all = -1; memset(las, -1, sizeof(las)); //all用原来的,las也记得清成-1
        for (int i = 1; i <= n; i++) {
            int ed = last[i], dr;
            while (ed != -1) {
                dr = other[ed];
                if (col[i] != col[dr] && !used[make_pair(col[i], col[dr])]) {
                    used[make_pair(col[i], col[dr])] = true;
                    rBuild(col[i], col[dr]);
                }
                ed = pre[ed];
            }
        }
    }
    
    void Solve()
    {
        Timetot = Scctot = 0;
        memset(dfn, 0, sizeof(dfn));    //dfn, low每次必须清空
        memset(low, 0, sizeof(low));
        memset(col, 0, sizeof(col));
        memset(ind, 0, sizeof(ind));
        memset(oud, 0, sizeof(oud));
        for (int i = 1; i <= n; i++) 
            if (!dfn[i]) Dfs_Scc(i, -1);
        ReBuildGraph();
        memset(usedused, 0, sizeof(usedused));
        int num = 0;
        for (int i = 1; i <= n; i++) {
            if (!usedused[col[i]]) {
                usedused[col[i]] = true;
                num++;
            }
        }
        memset(usedind, 0, sizeof(usedind));
        memset(usedoud, 0, sizeof(usedoud));
        int sum_ind = 0, sum_oud = 0;
        for (int i = 1; i <= n; i++) {
            if (ind[col[i]] == 0 && !usedind[col[i]]) {
                usedind[col[i]] = true;
                sum_ind++;
            }
            if (oud[col[i]] == 0 && !usedoud[col[i]]) {
                usedoud[col[i]] = true;
                sum_oud++;
            }
        }
        if (num == 1) printf("0
    ");
        else printf("%d
    ", max(sum_ind, sum_oud));
    }
    
    int main()
    {
        scanf("%d", &T);
        for (int cas = 1; cas <= T; cas++) {
            Init();
            Solve();
        }
        return 0;
    }

    #include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <stack>#include <vector>#include <map>#include <algorithm>usingnamespacestd; constint MaxN = 50000, MaxM = 200000; int T, n, m, all, Timetot, Scctot; int pre[MaxM + 5], last[MaxN + 5], other[MaxM + 5]; int pr[MaxM + 5], las[MaxN + 5], oth[MaxM + 5]; int dfn[MaxN + 5], low[MaxN + 5], col[MaxN + 5]; int ind[MaxN + 5], oud[MaxN + 5]; bool usedind[MaxN + 5], usedoud[MaxN + 5], usedused[MaxN + 5]; stack <int> sta; vector <int> Scc[MaxN + 5]; map <pair<int, int>, bool> used; void Build(int x, int y) { pre[++all] = last[x]; last[x] = all; other[all] = y; } void Init() { all = -1; memset(last, -1, sizeof(last)); scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); Build(u, v); } } void Dfs_Scc(int x, int fa) { dfn[x] = low[x] = ++Timetot; sta.push(x); //强连通分量 存点不存边int ed = last[x], dr; while (ed != -1) { dr = other[ed]; if (!dfn[dr]) { Dfs_Scc(dr, x); low[x] = min(low[x], low[dr]); } elseif (!col[dr] && dfn[dr] < dfn[x]) { low[x] = min(low[x], dfn[dr]); } ed = pre[ed]; } if (low[x] >= dfn[x]) { //强连通分量注意是while出来以后判 Scc[++Scctot].clear(); while (true) { int u = sta.top(); sta.pop(); col[u] = Scctot; Scc[Scctot].push_back(u); if (u == x) break; } } } void rBuild(int x, int y) { pr[++all] = las[x]; las[x] = all; oth[all] = y; ind[x]++; oud[y]++; } void ReBuildGraph() { used.clear(); all = -1; memset(las, -1, sizeof(las)); //all用原来的,las也记得清成-1for (int i = 1; i <= n; i++) { int ed = last[i], dr; while (ed != -1) { dr = other[ed]; if (col[i] != col[dr] && !used[make_pair(col[i], col[dr])]) { used[make_pair(col[i], col[dr])] = true; rBuild(col[i], col[dr]); } ed = pre[ed]; } } } void Solve() { Timetot = Scctot = 0; memset(dfn, 0, sizeof(dfn)); //dfn, low每次必须清空memset(low, 0, sizeof(low)); memset(col, 0, sizeof(col)); memset(ind, 0, sizeof(ind)); memset(oud, 0, sizeof(oud)); for (int i = 1; i <= n; i++) if (!dfn[i]) Dfs_Scc(i, -1); ReBuildGraph(); memset(usedused, 0, sizeof(usedused)); int num = 0; for (int i = 1; i <= n; i++) { if (!usedused[col[i]]) { usedused[col[i]] = true; num++; } } memset(usedind, 0, sizeof(usedind)); memset(usedoud, 0, sizeof(usedoud)); int sum_ind = 0, sum_oud = 0; for (int i = 1; i <= n; i++) { if (ind[col[i]] == 0 && !usedind[col[i]]) { usedind[col[i]] = true; sum_ind++; } if (oud[col[i]] == 0 && !usedoud[col[i]]) { usedoud[col[i]] = true; sum_oud++; } } if (num == 1) printf("0 "); elseprintf("%d ", max(sum_ind, sum_oud)); } int main() { scanf("%d", &T); for (int cas = 1; cas <= T; cas++) { Init(); Solve(); } return0; }

  • 相关阅读:
    性能分析之– JAVA Thread Dump 分析
    定位性能问题的18个linux命令
    jstat命令查看jvm的GC情况
    jstat命令查看tomcat进程提示进程没找到(PID not found
    Linux使用jstat命令查看jvm的GC情况
    jmeter -xml日志格式中网络时间与服务器时间的区分
    性能测试之----瓶颈分析方法
    jmeter dubbo接口测试
    java的 IO流之缓冲流(转载)
    java 中流的使用
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7568530.html
Copyright © 2011-2022 走看看