[题解]
tarjan缩点,寻找强连通分量。ans=sigma(sumi*(sumi-1)/2)
#include<stdio.h> #include<vector> #include<stack> using namespace std; const int N=1e4+5; int n,m,sd,ans,pd,low[N],dfn[N],sum[N]; bool mark[N]; vector<int>g[N];stack<int>s; void tarjan(int u){ low[u]=dfn[u]=++pd; mark[u]=1; s.push(u); for(int &w:g[u]){ if(!dfn[w]){ tarjan(w); low[u]=min(low[u],low[w]); } else if(mark[w]){ low[u]=min(low[u],dfn[w]); } } if(low[u]==dfn[u]){ sd++; for(int x;;){ x=s.top();s.pop(); sum[sd]++; mark[x]=0; if(x==u) break; } } } int main(){ scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),g[x].emplace_back(y); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=sd;i++) ans+=(sum[i]-1)*sum[i]/2; printf("%d\n",ans); return 0; }
原文:https://www.cnblogs.com/shenben/p/12288033.html