D14 强连通分量 Tarjan 算法

视频链接:D14 强连通分量 Tarjan 算法_哔哩哔哩_bilibili

 

// Luogu P2863 [USACO06JAN]The Cow Prom S
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

const int N=10010;
int n,m,a,b;
vector<int> e[N]; 
int dfn[N],low[N],tot;
int stk[N],instk[N],top;
int scc[N],siz[N],cnt;

void tarjan(int x){
  //入x时,盖戳、入栈
  dfn[x]=low[x]=++tot;
  stk[++top]=x,instk[x]=1;
  for(int y : e[x]){
    if(!dfn[y]){//若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);//回x时更新low
    }
    else if(instk[y])//若y已访问且在栈中
      low[x]=min(low[x],dfn[y]);//在x时更新low
  }
  //离x时,收集SCC
  if(dfn[x]==low[x]){//若x是SCC的根
    int y; ++cnt;
    do{
      y=stk[top--];
      instk[y]=0;
      scc[y]=cnt;//SCC编号
      ++siz[cnt];//SCC大小
    }while(y!=x);
  }
}
int main(){
  cin>>n>>m;
  while(m--)
    cin>>a>>b, e[a].push_back(b);
  for(int i=1; i<=n; i++)//可能不连通
    if(!dfn[i]) tarjan(i);
   int ans=0;
   for(int i=1;i<=cnt;i++)
     if(siz[i]>1) ans++;
   cout<<ans<<endl;
  return 0;
}

 

// Luogu P2863 [USACO06JAN]The Cow Prom S
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;

const int N=10010;
int n,m,a,b;
vector<int> e[N];
int dfn[N],low[N],tot;
stack<int> stk;
int scc[N],siz[N],cnt;

void tarjan(int x){
  //入x时,盖戳、入栈
  dfn[x]=low[x]=++tot;
  stk.push(x);
  for(int y : e[x]){
    if(!dfn[y]){//若y尚未访问
      tarjan(y);
      low[x]=min(low[x],low[y]);//回x时
    }
    else if(!scc[y])//若y已访问且未处理
      low[x]=min(low[x],dfn[y]);//下x时
  }
  //离x时,记录SCC
  if(dfn[x]==low[x]){//若x是SCC的根
    ++cnt;
    while(1){
      int y=stk.top();stk.pop();
      scc[y]=cnt;//SCC编号
      ++siz[cnt];//SCC大小
      if(y==x)break;
    }
  }
}
int main(){
  cin>>n>>m;
  while(m--)
    cin>>a>>b, e[a].push_back(b);
  for(int i=1; i<=n; i++)//可能不连通
    if(!dfn[i]) tarjan(i);
   int ans=0;
   for(int i=1;i<=cnt;i++)
     if(siz[i]>1) ans++;
   cout<<ans<<endl;
  return 0;
}

 

posted @ 2022-05-28 13:28  董晓  阅读(1196)  评论(1编辑  收藏  举报