强连通缩点,复杂度
O
(
N
+
E
)
O(N+E)
O(N+E) 。 ps:N个点,E条边
有向图模版
vector<int> g[maxn];
int dfn[maxn],vis[maxn],low[maxn]; //vis 是否在栈中
int cnt=0;
int stk[maxn];
int ind=0,stp=0;
int ans[maxn]; //一个强连通块编号,按题目要求自行修改
void tarjan(int u){
dfn[u]=low[u]=++stp;
vis[u]=1; //最好用bool
stk[++ind]=u;
for(auto i:g[u]){
if(!dfn[i]){
tarjan(i);
low[u]=min(low[u],low[i]);
}else if(vis[i]){
low[u]=min(low[i],low[u]);
}
}
if(dfn[u]==low[u]){
++cnt;
do{
vis[stk[ind]]=0;
ans[stk[ind]]=cnt;
--ind;
}while(u!=stk[ind+1]);
}
}
无向图模版
vector<int> g[maxn],gg[maxn];
int tol=0,ind=0,ft=0;
bool vis[maxn];
int scc[maxn];
int sta[maxn];
int dfn[maxn],low[maxn];
void tarjan(int u,int f){
vis[u]=1;
sta[++ft]=u;
dfn[u]=low[u]=++tol;
for(auto i:g[u]){
if(!dfn[i]){
tarjan(i,u);
low[u]=min(low[u],low[i]);
}else if(vis[i]&&i!=f){ //关键在这
low[u]=min(low[u],low[i]);
}
}
if(low[u]==dfn[u]){
++ind;
do{
scc[sta[ft]]=ind;
vis[sta[ft]]=0;
ww[ind]+=w[sta[ft]];
ss[ind]+=1;
--ft;
}while(sta[ft+1]!=u);
}
}