Tarjan缩点经典题目:Popular Cows

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_44824275/article/details/93528267

一、题面

OpenJ_Bailian-2186

描述

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 is popular, 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.

输入

  • 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.

输出

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

样例输入

3 3
1 2
2 1
2 3

样例输出

1

提示

Cow 3 is the only cow of high popularity.

二、分析

根据该题的描述,我们发现整个herd就是一个有向图(不保证联通)
显然我们需要对其进行缩点,这里使用Tarjan算法求SCC
假设现在有三个SCC,有两条边, 2 1 2\rightarrow1 3 1 3\rightarrow1

我们很容易就能想到,对于没有出度的 1 1 来说,里面的所有点都是Popular Cow
如果同时存在两个或两个以上的出度为0的SCC,那么Popular Cow不存在,此题无解

整体思路如下

1.Tarjan求SCC
2.求出度为0的SCC的个数
3.如果个数为一,输出其对应SCC内点的个数;如果个数不是一,则输出0

三、代码实现

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>

using namespace std;
const int kmax = 10010,INF = 0x3f3f3f3f;

int n,m,a,b,sum,res,stamp,scc;
int low[kmax],dfn[kmax],sta[kmax],belong[kmax],out[kmax],num[kmax];
bool instack[kmax];
vector<int> edge[kmax];

inline long long read()
{
    register int w=1;
    register long long s=0;
    register char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*w;
}

inline void write(long long x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

void tarjan(int s)
{
    int sz=edge[s].size();
    sta[++stamp]=s;
    instack[s]=1;
    dfn[s]=low[s]=stamp;
    for(int i=0;i<sz;i++)
    {
        int to=edge[s][i];
        if(dfn[to]==-1)
        {
            tarjan(to);
            low[s]=min(low[s],low[to]);
        }
        else if(instack[to])
        {
            low[s]=min(low[s],dfn[to]);
        }
    }
    if(low[s]==dfn[s])
    {
        scc++;
        do
        {
            int to=sta[stamp];
            belong[to]=scc;
            instack[to]=0;
            num[scc]++;
        }
        while(sta[stamp--]!=s);
    }
}

int main()
{
    n=read(),m=read();
    memset(dfn,-1,sizeof(dfn));
    while(m--)
    {
        a=read(),b=read();
        edge[a].push_back(b);
    }
    for(int i=1;i<=n;i++)
    {
        if(dfn[i]==-1)
        {
            tarjan(i);
        }
    }
    for(int i=1;i<=n;i++)
    {
        int sz=edge[i].size();
        for(int j=0;j<sz;j++)
        {
            int to=edge[i][j];
            if(belong[i]!=belong[to])
            {
                out[belong[i]]++;
            }
        }
    }
    for(int i=1;i<=scc;i++) if(out[i]==0) res=i,sum++;
    if(sum>1) putchar('0'),putchar('\n');
    else write(num[res]),putchar('\n');
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44824275/article/details/93528267
今日推荐