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

 

转载于:https://www.cnblogs.com/tanhehe/archive/2013/06/04/3117785.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值