RT
可能代码复杂了一点,思路就是先缩点,再看是不是所有点都能到某个点,如果能答案就加上这个点的权值(强连通分量的大小)。
请大佬指教。
#include <bits/stdc++.h>
using namespace std;
int n, m;
int u, v;
vector <int> g[10005];
vector <int> rg[10005];
vector <int> ng[10005];
bool vis[10005];
int s[10005], top;
int c[10005], sum;
int val[10005];
int in[10005];
int ans;
void dfs(int u)
{
if(vis[u] == true) return;
vis[u] = true;
for(int i=0; i<g[u].size(); i++){
int v = g[u][i];
dfs(v);
}
s[++top] = u;
}
void rdfs(int u)
{
if(c[u] != 0) return;
c[u] = sum;
for(int i=0; i<rg[u].size(); i++){
int v = rg[u][i];
rdfs(v);
}
}
void Kosaraju()
{
top = 0;
sum = 0;
for(int i=1; i<=n; i++){
vis[i] = false;
c[i] = 0;
}
for(int i=1; i<=n; i++) dfs(i);
for(int i=top; i>=1; i--){
if(c[s[i]] == 0){
sum++;
rdfs(s[i]);
}
}
}
void shrink()
{
for(int i=1; i<=n; i++){
val[c[i]]++;
for(int j=0; j<g[i].size(); j++){
int u, v;
u = c[i];
v = c[g[i][j]];
if(u == v) continue;
ng[u].push_back(v);
in[v]++;
}
}
}
void ndfs(int u, int k)
{
k++;
if(k == sum) ans += val[u];
for(int i=0; i<ng[u].size(); i++){
int v = ng[u][i];
ndfs(v, k);
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i=1; i<=m; i++){
scanf("%d%d", &u, &v);
g[u].push_back(v);
rg[v].push_back(u);
}
Kosaraju();
shrink();
for(int i=1; i<=sum; i++){
if(in[i] == 0){
ndfs(i, 0);
}
}
printf("%d", ans);
return 0;
}