Popular cattle (strongly connected components)

Popular cow

Title

Now has NNN cows, numbered from1 to 11 toNNN , give youMMM pairs of integers(A, B) (A, B)(A,B ) , means cattleAAA thinks bullBBB is popular. This relationship is transitive, ifAAA thinksBBB is popular,BBB thinksCCC is popular, so beefAAA also thinks cattleCCC is popular. Find out how many cows are considered popular by all cows except yourself.

data range

1 ≤ N ≤ 1 0 4 1 \ leq N \ leq 10 ^ 4 1N104
1 ≤ M ≤ 5 ∗ 1 0 4 1 \leq M \leq 5*10^4 1M5104

Ideas

This question builds up the graph and forms a directed graph. But directed graphs are not easy to handle, so consider shrinking points.
We directly consider the reduced DAG. Obviously, only points with a degree of 0 can meet the requirements, so we only focus on points with a degree of 0.
If there is more than one point with a degree of 0, then there must be no point that meets the requirements, because they cannot be popular with each other.
So the final result is the number of points in the strongly connected components whose out-degree is 0.

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>

using namespace std;

const int N = 10010, M = 50010;

int n,m;
int h[N], e[M], ne[M], idx;
int scc_cnt, timestamp;
bool in_stk[N];
int id[N], sz[N], dfn[N], low[N];
stack<int> stk;;
int dout[N];

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

void tarjan(int u)
{
    
    
    low[u] = dfn[u] = ++ timestamp;
    stk.push(u), in_stk[u] = true;
    for(int i=h[u];~i;i=ne[i]){
    
    
        int j = e[i];
        if(!dfn[j]){
    
    
            tarjan(j);
            low[u] = min(low[j], low[u]);
        }
        else if(in_stk[j]) low[u] = min(low[u], dfn[j]);
    }
    if(dfn[u]==low[u]){
    
    
        int v;
        scc_cnt ++;
        do{
    
    
            v = stk.top();
            stk.pop();
            in_stk[v] = false;
            id[v] = scc_cnt;
            sz[scc_cnt] ++;
        }while(u!=v);
    }
}

int main()
{
    
    
    cin >> n >> m;
    memset(h,-1,sizeof(h));
    for(int i=1;i<=m;i++){
    
    
        int a,b;
        cin >> a >> b;
        add(a,b);
    }
    for(int i=1;i<=n;i++){
    
    
        if(!dfn[i]){
    
    
            tarjan(i);
        }
    }
    for(int i=1;i<=n;i++){
    
    
        for(int j=h[i];~j;j=ne[j]){
    
    
            int k = e[j];
            int a = id[i], b = id[k];
            if(a!=b) dout[a] ++;
        }
    }
    int zeros = 0, sum = 0;
    for(int i=1;i<=scc_cnt;i++){
    
    
        if(!dout[i]){
    
    
            zeros ++;
            sum += sz[i];
            if(zeros>1){
    
    
                sum = 0;
                break;
            }
        }
    }
    cout << sum << endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43634220/article/details/108659335