割点/割边

void dfs(int x, int fa) {
	dfn[x] = low[x] = ++ tot;
	for(unsigned int i = 0; i < v[x].size(); i ++) {
		int Y = v[x][i]; if(Y == fa) continue;
		if(!dfn[Y]) { // 树边 
			dfs(Y, x); low[x] = Min(low[Y], low[x]);
			if(low[Y] >= dfn[x]) (~fa) ? vis[x] = 1 : rts ++;
			if(low[Y] > dfn[x]) cnt2 ++;
		}
		else low[x] = Min(dfn[Y], low[x]);
	}
}

强连通

void dfs(int x) {
	dfn[x] = ++ tot; low[x] = tot; s[++ cnt] = x;
	for(uint i = 0; i < v[x].size(); i ++) {
		int y = v[x][i];
		if(!dfn[y]) dfs(y), low[x] = min(low[x], low[y]);
		else if(!col[y]) low[x] = min(low[x], dfn[y]);
	}
	if(dfn[x] == low[x]) {
		nk ++; int t;
		do {
			t = s[cnt --]; col[t] = nk;
		} while(t != x);
	}
}

边双

void dfs(int x, int fa) { // 缩点 
	s.push(x); dfn[x] = low[x] = ++ tot;
	for(int i = Head[x]; i; i = Next[i]) {
		int Y = Ver[i]; if(Y == fa) continue;
		if(!dfn[Y]) {
			dfs(Y, x); low[x] = Min(low[x], low[Y]);
		}
		else low[x] = Min(low[x], dfn[Y]);
	}
	if(dfn[x] == low[x]) {
		cnt ++;
		int t;
		do {
			t = s.top(); s.pop(); color[t] = cnt;
		} while(t != x);
	}
}


点双(待更新)