Tarjan算法

2024-08-14

采用Tarjan算法,判断图中是否有强连通分量

#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
const int N = 100005;
int cnt;
int low[N], num[N], dfn;
int sccno[N], stack[N], top;
vector<int> G[N];
void dfs(int u)
{
    stack[top++] = u;
    low[u] = num[u] = ++dfn;
    for (int i = 0; i < G[u].size(); i++)
    {
        int v = G[u][i];
        if (!num[v])
        {
            dfs(v);
            low[u] = min(low[u], low[v]);
        }
        else if (!sccno[v])
            low[u] = min(low[u], num[v]);
    }
    if (low[u] == num[u])
    {
        cnt++;
        while (1)
        {
            int v = stack[--top];
            sccno[v] = cnt;
            if (u == v)
                break;
        }
    }
}
void Tarjan(int n)
{
    cnt = top = dfn = 0;
    memset(sccno, 0, sizeof(sccno));
    memset(num, 0, sizeof(num));
    memset(low, 0, sizeof(low));
    for (int i = 1; i <= n; i++)
        if (!num[i])
            dfs(i);
}
int main()
{
    int n, m, u, v;
    while (scanf("%d%d", &n, &m), n != 0 || m != 0)
    {
        for (int i = 1; i <= n; i++)
            G[i].clear();
        for (int i = 0; i < m; i++)
        {
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
        }
        Tarjan(n);
        printf("%s\n", cnt == 1 ? "Yes" : "No");
    }
    return 0;
}