题目大概意思为有 N 头牛,有些牛认为有些牛是红人,该关系具有传递性,例如果牛A觉得牛B是红人,牛B认为牛C是红人,则牛A也会认为牛C是红人,求被其他所有牛认为是红人的牛的总数
假设被其他所有牛认为是红人的牛的点集为 S ,由于被是被其他所有牛觉得是红人,因此最后点集内的牛,都互相认为是红人,所以为强连通分量
我们将原图强连通分量分解后,只有最接近图的末尾的强连通分量有可能是题目结果,因此我们取强连通分量中编号最后的强连通分量 点集S(即图最末尾的)进行判断
取 点集S 中任意一点(该点集内互通,所以取哪一点不重要),如果该点能通过反向边到达图中任意一点,则证明 点集S 符合题意
否则答案为0
套模板即可,代码如下:
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
using namespace std;
vector<int> data[10005];
vector<int> rdata[10005];
vector<int> flag;
int used[10005];
int kind[10005];
void add_edge(int i, int j)
{
data[i].push_back(j);
rdata[j].push_back(i);
}
void dfs(int v)
{
used[v] = true;
for(int i = 0; i < data[v].size(); i++)
{
if(!used[data[v][i]])
{
dfs(data[v][i]);
}
}
flag.push_back(v);
}
void rdfs(int v, int k)
{
used[v] = true;
kind[v] = k;
for(int i = 0; i < rdata[v].size(); i++)
{
if(!used[rdata[v][i]])
{
rdfs(rdata[v][i], k);
}
}
}
int main()
{
int N, M;
scanf("%d %d", &N, &M);
for(int i = 0; i < M; i++)
{
int a, b;
scanf("%d %d", &a, &b);
add_edge(a - 1, b - 1);
}
memset(used, false, sizeof(used));
for(int i = 0; i < N; i++)
{
if(!used[i])
{
dfs(i);
}
}
memset(used, false, sizeof(used));
int num = 0;
for(int i = flag.size() - 1; i >= 0; i--)
{
if(!used[flag[i]])
{
rdfs(flag[i], num);
num++;
}
}
int p, q = 0;
for(int i = 0; i < N; i++)
{
if(kind[i] == num - 1)
{
p = i;
q++;
}
}
memset(used, false, sizeof(used));
rdfs(p, -1);
for(int i = 0; i < N; i++)
{
if(!used[i])
{
q = 0;
break;
}
}
printf("%d\n", q);
}