zoukankan      html  css  js  c++  java
  • The Largest SCC(强连通分量)

    题目链接

    The Largest SCC

    题目描述

    Consider a directed graph with N (1 <= N <= 1000) vertices and M (0 <= M <= 20000) edges. The edges are numbered from 1 to M and the vertices are numbered from 1 to N. Now I will make ONE edge bidirectional, and you are to tell me the number of vertices of the largest strong connected components in the new graph.The largest strong connected components is the strong connected components which has the most vertices. After the operation, I will change the edge back. There will be up to Q (1 <= Q <= 20000) such queries.

    输入

     At the firest of the input comes an integer t, indicates the testcases to follow. The first line of each case contains three numbers N, M and Q. Then there will be M lines, each of them contains two numbers a,b (a! = b; 1 <= a; b <= N) means there is a directed edge between a and b. The last of each case contains Q lines, each of them contains one integer q, means the edge numbered q will be change to bidirectional. There will not be duplicated edges.

    输出

     For every query, output one line contains only one integer number, which is the number of vertices of the biggest strong connected components.

    示例输入

    1
    5 4 2
    1 2
    2 3
    1 3
    4 1
    1
    3

    示例输出

    2
    3

    分析:

    假设在不改变任何边时,含强连通分量含定点数最多为 max_scc, 那么操作时,如果要改变的一条边的两个点在同一个强连通分量中, 那么答案就是 max_scc, 否则就重新计算。

    注意:

    每条边改变后,还会恢复。

    同一强连通分量中时 max_scc 要和 2 进行比较(不太清楚为啥)。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <stack>
    
    using namespace std;
    
    const int maxn = 1000 + 100;
    const int maxm = 20000 + 10;
    
    vector<int> G[maxn];
    stack<int> S;
    int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt, u[maxm], v[maxm], max_scc;
    
    void dfs(int u) {
        pre[u] = lowlink[u] = ++dfs_clock;
    
        S.push(u);
    
        for(int i=0; i<G[u].size(); i++) {
            int v = G[u][i];
            if(!pre[v]) {
                dfs(v);
                lowlink[u] = min(lowlink[u], lowlink[v]);
            } else if(!sccno[v]) {
                lowlink[u] = min(lowlink[u], pre[v]);
            }
        }
    
        if(lowlink[u] == pre[u]) {
            scc_cnt++;
            int cc = 0;
            for(;;) {
                int x = S.top(); S.pop();
                sccno[x] = scc_cnt;
                cc++;
                if(x == u) break;
            }
            max_scc = max(max_scc, cc); //统计
        }
    }
    
    void find_scc(int n) {
        dfs_clock = scc_cnt = 0;
        memset(sccno, 0, sizeof(sccno));
        memset(pre, 0, sizeof(pre));
        for(int i=0; i<n; i++)
            if(!pre[i]) dfs(i);
    }
    
    int main(){
        int T, n, m, q;
        scanf("%d", &T);
        while(T--){
            scanf("%d%d%d", &n, &m, &q);
            for(int i=0; i<n; i++) G[i].clear();
    
            for(int i=1; i<=m; i++) {
                scanf("%d%d", &u[i], &v[i]);
                u[i]--; v[i]--;
                G[u[i]].push_back(v[i]);
            }
    
            max_scc = 0;
            find_scc(n);
    
            while(q--) {
                int order, temp = max_scc;
                cin >> order;
    
                if(sccno[v[order]] == sccno[u[order]]) { printf("%d\n", max(max_scc, 2)); continue; }
    
                G[v[order]].push_back(u[order]);
    
                find_scc(n);
    
                printf("%d\n", max_scc);
    
                max_scc = temp;
    
                G[v[order]].resize(G[v[order]].size()-1);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    Thinkphp中如何书写按照指定字段同步更新的ORM
    一道money计算题引发的思考
    娱乐一下:汤姆君的大转盘算法(搞笑版)
    php导出数组到csv格式demo
    通过xshell/securecrt连接linux上传/下载文件
    windows设置代理.bat 脚本
    【面试题】输入并保存文件,完成后退出显示文件内容
    【设计模式学习笔记】 之 状态模式
    【学习笔记】FreeMarker 之于Servlet与Stuts2的应用
    【学习笔记】初识FreeMarker简单使用
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3117785.html
Copyright © 2011-2022 走看看