Tarjan 模板:
情景说明:
n个点 m条边
目的:输出多个点组成的强连通分量数,并给新的图上的点编码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
const int maxn=1.5e3;
const int maxm=1.5e4;
struct Edge
{
int from,to,next;
Edge() {}
Edge(int f,int t,int n):from(f),to(t),next(n) {}
}edges[maxn]; int pre[maxn],cnt;
int n,m;
stack<int> st;
int state[maxn],dfn[maxn],low[maxn],dfsclock; //state记录当前点的状态 dfsclock记录递归顺序
int id[maxn],node,ans; // 编码记录
int init()
{
cnt=0;
memset(pre,-1,sizeof(pre));
memset(state,0,sizeof(state));
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int u,v; scanf("%d%d",&u,&v);
edges[cnt]=Edge(u,v,pre[u]); pre[u]=cnt++;
} return 0;
}
int tarjan(int u)
{
dfn[u]=low[u]=dfsclock++;
st.push(u); state[u]=1;
for (int i=pre[u];i!=-1;i=edges[i].next)
{
int v=edges[i].to;
if (state[v]==0) { //v没有访问过
tarjan(v);
low[u]=min(low[u],low[v]);
} else if (state[v]==1) { //v在访问中
low[u]=min(low[u],low[v]);
}
}
if (dfn[u]==low[u]) {
node++;
if (st.top()==u) ans--; //只有一个点
while (st.top()!=u) {
int v=st.top(); st.pop();
id[v]=node; state[v]=2; //访问完成
}
id[u]=node; st.pop(); state[u]=2; ans++;
}
}
int work()
{
node=0; ans=0;
for (int i=1;i<=n;i++) {
if (!state[i]) {
dfsclock=0;
tarjan(i);
}
}
printf("%d",ans);
}
int main()
{
init();
work();
return 0;
}