P11073 Game King

P11073 Game King - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

缩点,分别重建图,再建反图,可知,拓扑序大的一定不能到拓扑序小的。不断新建点统计。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>
#include <queue>

using namespace std;

typedef pair<int, int> PII;

const int N = 1000010, M = N * 12;

int h[N], ne[M], e[M], idx, hr[N], hx[N];
int n, m, ans;

int dfn[N], low[N], timestamp;
int stk[N], top;
bool in_stk[N];
int id[N], scc_cnt, sizes[N];
int din[N], dout[N], din1[N], dout1[N];
double s1[N], s2[N];
int st[N];

void add(int *h, int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void tarjan(int u)
{
    dfn[u] = low[u] = ++ timestamp;
    stk[ ++ top] = u; in_stk[u] = true;
    
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!dfn[j])
        {
            tarjan(j);
            low[u] = min(low[u], low[j]);
        }
        else if (in_stk[j]) low[u] = min(low[u], dfn[j]);
    }
    
    if (low[u] == dfn[u])
    {
        scc_cnt ++ ;
        
        int y;
        do {
            y = stk[top -- ];
            id[y] = scc_cnt;
            sizes[scc_cnt] ++ ;
            in_stk[y] = false;
        }while (y != u);
    }
}

int main()
{
    cin >> n >> m;
    
    
    memset(h, -1, sizeof h);
    memset(hr, -1, sizeof hr);
    memset(hx, -1, sizeof hx);
    while (m -- )
    {
        int a, b;
        scanf("%d%d", &a, &b);
        if (a == b) continue;
        add(h, a, b);
    }
    
    int cnt = 0;
    for (int i = 1; i <= n; i ++ )
        if (dfn[i] == 0)
        {
            tarjan(i);
            cnt ++ ;
        }
        
    
    for (int u = 1; u <= n; u ++ )
    {
        for (int i = h[u]; i != -1; i = ne[i]) 
        {
            int j = e[i], a = id[u], b = id[j];
            if (b != a)
            {
                add(hr, a, b); 
                add(hx, b, a);
            }
        }
    }
    
    
    int zero = 0, ans = 0; // 入度为零点数量,ans统计
    for (int u = 1; u <= scc_cnt; u ++ )
    {
        zero ++ ;
        for (int i = hr[u]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (din[j] == 0) zero -- ; 
            din[j] ++ ;
        }
        
        if (zero == 1) st[u] = 1;
    }
    
    zero = 0;
    
    for (int u = scc_cnt; u; u -- )
    {
        zero ++ ;
        for (int i = hx[u]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dout[j] == 0) zero -- ; 
            dout[j] ++ ;
        }
        if (zero == 1 && st[u]) ans += sizes[u];
    }
    
    cout << ans << endl;
    return 0; 
}
posted @ 2024-10-13 14:22  blind5883  阅读(3)  评论(0编辑  收藏  举报