【CCF】高速公路 tarjan强连通缩点
【题意】
给定一个有向图,问图中互相可达(强连通)的点有多少对
【AC】
强连通缩点,缩点后是一个DAG,所以互相可达的点只在强连通块里。
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> using namespace std; int n,m; const int maxn=1e4+2; const int maxm=1e5+2; struct edge{ int to; int nxt; }e[maxm]; int head[maxn]; int tot; int S[maxn],top; int dfn[maxn],low[maxn],id; int belong[maxn],num; bool vis[maxn]; int circle[maxn]; void init(){ memset(head,-1,sizeof(head)); tot=0; id=top=num=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,false,sizeof(vis)); memset(circle,0,sizeof(circle)); } void add(int u,int v){ e[tot].to=v; e[tot].nxt=head[u]; head[u]=tot++; } void tarjan(int u) { dfn[u]=low[u]=++id; S[++top]=u; vis[u]=true; for(int i=head[u];i!=-1;i=e[i].nxt) { int v=e[i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { num++; while(1) { belong[S[top]]=num; vis[S[top]]=false; if(S[top--]==u) break; } } } int main(){ while(~scanf("%d%d",&n,&m)){ init(); int u,v; for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); add(u,v); } for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } for(int i=1;i<=n;i++){ circle[belong[i]]++; } int ans=0; for(int i=1;i<=num;i++){ ans+=circle[i]*(circle[i]-1)/2; } printf("%d\n",ans); } return 0; }