时间限制 : 1 秒
内存限制 : 128 MB
有一个 nn 个点,mm 条边的有向图,请求出这个图点数大于 11 的强连通分量个数。
输入
第一行为两个整数 nn 和 mm。
第二行至 m+1m+1 行,每一行有两个整数 aa 和 bb,表示有一条从 aa 到 bb 的有向边。
输出
仅一行,表示点数大于 11 的强连通分量个数。
样例
输入
5 4 2 4 3 5 1 2 4 1
输出
1
提示
数据规模与约定
对于全部的测试点,保证 2≤n≤1042≤n≤104,2≤m≤5×1042≤m≤5×104,1≤a,b≤n1≤a,b≤n。
———————————————————————————————————————————
代码:
这里用的是kosaraju算法
#include<bits/stdc++.h>
using namespace std;
int n,m;
vector<int>g[10002];
vector<int>zg[10002];
int d[10002];
int v[10002];
int sum[10002];
int t=0;
void dfs1(int x)
{
v[x]=1;
for(int i=0;i<g[x].size();i++)
{
int ee=g[x][i];
if(v[ee]!=1) dfs1(ee);
}
d[++t]=x;
}
void dfs2(int x)
{
v[x]=t;
for(int i=0;i<zg[x].size();i++)
{
int ee=zg[x][i];
if(v[ee]==0) dfs2(ee);
}
}
void Kosaraju()
{
t=0;
for(int i=1;i<=n;i++)
if(!v[i]) dfs1(i);
memset(v,0,sizeof(v));
t=0;
for(int i=n;i>=1;i--)
if(v[d[i]]==0)
{
t++;
dfs2(d[i]);
}
for(int i=1;i<=n;i++) sum[v[i]]++;
int ans=0;
for(int i=1;i<=n;i++)
if(sum[i]>=2) ans++;
cout<<ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
g[a].push_back(b);
zg[b].push_back(a);
}
Kosaraju();
return 0;
}