Tarjan算法 计算有向图的强连通量(可作为模板)-------CCF CSP 高速公路-CSDN博客

70 阅读3分钟

CCF CSP竟然出了道模板题。Targan算法计算有向图的强连通分量,时间复杂度O(n + m)。

对于这个模板,得懂得每个变量和数组的含义,才能灵活运用模板。scc为强连通分量。num[]为各个强连通分量包含的点数。

对于该题,计算出num[]后,对于num[]大于等于2的强连通分量点数累加一次组合数C(n, 2)就可以了。

静态前向星存图,这个targan算法摘自上海大学ACM的模板。致谢

#include <cstdio>
#include <cstring>
const int N = 1e4 + 7, M = 1e5 + 7;
struct Edge {
    int to, nxt;
}e[M];
int head[N], tot;
int low[N], dfn[N], st[N], belong[N];//belong数组的值是1:scc
int idx, top, scc;//强连通分支数
bool in[N]; //instack
int num[N]; //强联通分量包含的点数,不一定需要
void init() {
    tot = 0;
    memset(head, -1, sizeof head);
}
void add(int u, int v) {
    e[tot].to = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}
void tarjan(int u) {
    int v;
    low[u] = dfn[u] = ++idx;
    st[top++] = u;
    in[u] = true;
    for (int i = head[u]; ~i; i = e[i].nxt) {
        v = e[i].to;
        if(!dfn[v]) {
            tarjan(v);
            if(low[u] > low[v]) low[u] = low[v];
        }
        else if(in[v] && low[u] > dfn[v]) low[u] = dfn[v];
    }
    if(low[u] == dfn[u]) {
        scc++;
        do {
            v = st[--top];
            in[v] = false;
            belong[v] = scc;
            num[scc]++;
        } while(v != u);
    }
}
void solve(int n) {
    memset(dfn, 0, sizeof dfn);
    memset(in, 0, sizeof in);
    memset(num, 0, sizeof num);
    idx = scc = top = 0;
    for (int i = 1; i <= n; ++i) {
        if(!dfn[i]) tarjan(i);
    }
}
int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m)) {
        init();
        for (int i = 0; i< m; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
        }
        solve(n);
        int cnt = 0;
        for (int i = 1; i<= n; ++i) {
            //printf("%d%c", num[i], " \n"[i == n]);
            if(num[i] >= 2)
                cnt += num[i] * (num[i] - 1) / 2;
        }
        printf("%d\n", cnt);
    }

    return 0;
}

问题描述

试题编号:201509-4
试题名称:高速公路
时间限制:1.0s
内存限制:256.0MB
问题描述:问题描述  某国有 n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路。   现在,大臣们帮国王拟了一个修高速公路的计划。看了计划后,国王发现,有些城市之间可以通过高速公路直接(不经过其他城市)或间接(经过一个或多个其他城市)到达,而有的却不能。如果城市A可以通过高速公路到达城市B,而且城市B也可以通过高速公路到达城市A,则这两个城市被称为便利城市对。   国王想知道,在大臣们给他的计划中,有多少个便利城市对。输入格式  输入的第一行包含两个整数 n,  m,分别表示城市和单向高速公路的数量。   接下来 m行,每行两个整数 a,  b,表示城市 a有一条单向的高速公路连向城市 b。输出格式  输出一行,包含一个整数,表示便利城市对的数量。样例输入5 5 1 2 2 3 3 4 4 2 3 5样例输出3样例说明   城市间的连接如图所示。有3个便利城市对,它们分别是(2, 3), (2, 4), (3, 4),请注意(2, 3)和(3, 2)看成同一个便利城市对。评测用例规模与约定  前30%的评测用例满足1 ≤  n ≤ 100, 1 ≤  m ≤ 1000;   前60%的评测用例满足1 ≤  n ≤ 1000, 1 ≤  m ≤ 10000;   所有评测用例满足1 ≤  n ≤ 10000, 1 ≤  m ≤ 100000。


\

\

\