Popular Cows (strongly connected components + tarjan algorithm)

Detailed explanation of strong connected component + tarjan algorithm:

Popular Cows

Every cow’s dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C ispopular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.

input

  • Line 1: Two space-separated integers, N and M
  • Lines 2…1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.

output

  • Line 1: A single integer that is the number of cows who are considered popular by every other cow.

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
const int MAXN=5e4+5;
const int M=1e4+5;
typedef long long ll;
int col=0,num=0,top=0,dfn[M],low[M];
int deep[M];
int si[M];
int st[M];
int co[M];
struct edge
{
    
    
    int to;
    int next;
}e[MAXN];
int head[M];
int cnt=0;
void add(int u,int v)
{
    
    
    e[cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void tarjan(int u)//缩点
{
    
    
    dfn[u]=low[u]=++num;
    st[++top]=u;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
    
    
        int v=e[i].to;
        if(!dfn[v])//没有搜过,则搜这个点
        {
    
    
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!co[v])//搜过这个点,若不在集合中,代表还在堆栈中。
        {
    
    
            low[u]=min(low[u],low[v]);
        }
    }
    if(dfn[u]==low[u])//出栈
    {
    
    
        co[u]=++col;//记录第几个集合
        si[col]++;//记录集合中元素数量
        while(st[top]!=u)
        {
    
    
            co[st[top]]=col;
            si[col]++;
            top--;
        }
        top--;
    }
}
int main()
{
    
    
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
    
    
        head[i]=-1;
        dfn[i]=0;
        low[i]=0;
        co[i]=0;
        si[i]=0;
        deep[i]=0;
    }
    int u,v;
    for(int i=1;i<=m;i++)
    {
    
    
        scanf("%d%d",&u,&v);
        add(v,u);//反向建图
    }
    for(int i=1;i<=n;i++)
    {
    
    
        if(!dfn[i])
        {
    
    
            tarjan(i);
        }
    }
    for(int i=1;i<=n;i++)
    {
    
    
        for(int j=head[i];j!=-1;j=e[j].next)
        {
    
    
            int v=e[j].to;
            if(co[v]!=co[i])//判断是否在同一个集合里面
            {
    
    
                deep[co[v]]++;//若不在,则入度++
            }
        }
    }
    int ans=0,sum=0;
    for(int i=1;i<=col;i++)
    {
    
    
        if(!deep[i]) {
    
    ans=si[i];sum++;}
    }
    if(sum==1) printf("%d",ans);//若sum>1,说明有多个入度为0的分量,反过来就是无出度,说明不会被所有的的牛喜欢。
    else printf("0");
}

Guess you like

Origin blog.csdn.net/weixin_45755679/article/details/107391384