atcoder.jp/contests/ty…
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=1<<18;
int n,m;int a[N],b[N];
bool us[N];
vector<int>g[N];
vector<int>h[N];
vector<int>I;
ll cnts;
//记录后序遍历序列
void dfs(int pos){
us[pos]=true;
for(int i:g[pos]){
if(!us[i])dfs(i);
}I.push_back(pos);
}
void dfs2(int pos){//反图
us[pos]=true;
cnts++;
for(int i:h[pos]){if(!us[i])dfs2(i);}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i]>>b[i];
g[a[i]].push_back(b[i]);
h[b[i]].push_back(a[i]);
}for(int i=1;i<=n;i++){
if(!us[i])dfs(i);
}ll ans=0;
reverse(I.begin(),I.end());
fill(us,us+n+1,false);
for(int i:I){
if(us[i])continue;
cnts=0;
dfs2(i);
ans+=cnts*(cnts-1ll)/2ll;
}
cout<<ans;
}
思路
原图 DFS: 能到达别人的点会后结束 反图 DFS: 从后结束的点开始搜 只能搜到互相可达的点 刚好就是一个强连通分量!