【模板】Tarjan求点双连通分量


#include
using namespace std;
const int z = 131072;
int n, m;
int _ = -1;

struct line{
	int t, next;
} edge[z<<3];
int cnt, head[z];
void adedge(int &f,int &t) {
	edge[++cnt].next = head[f];
	edge[cnt].t = t;
	head[f] = cnt;
	return;
}

stack stk;
vector pbcc[z], belong[z];
int dfn[z], low[z], ti, tot;
bool cp[z];
int pbccnt[z];
void tarjan(int &u,int &p) {
	dfn[u] = low[u] = ++ti;
	stk.push(u);
	bool fsl = false;
	int sub = 0;
	for(int i = head[u];i;i = edge[i].next) {
		if(!fsl&&edge[i].t == p) {
			fsl = true;
			continue;
		}
		if(!dfn[edge[i].t]) {
			++sub;
			tarjan(edge[i].t,u);
			low[u] = min(low[u],low[edge[i].t]);
			if(dfn[u] <= low[edge[i].t]) {
				cp[u] = true;
				++tot;
				pbcc[tot].push_back(u);
				int tmp;
				do {
					tmp = stk.top();
					stk.pop();
					pbcc[tot].push_back(tmp);
					belong[tmp].push_back(tot);
				} while(tmp != edge[i].t);
			}
		} else {
			low[u] = min(low[u],dfn[edge[i].t]);
		}
	}
	if(p == -1&&sub == 1) 
		cp[u] = false;
	return;
}

int main() {
	scanf("%d %d",&n,&m);
	for(int i = 1;i <= m;++i) {
		int f, t;
		scanf("%d %d",&f,&t);
		adedge(f,t);
		adedge(t,f);
	}
	for(int i = 1;i <= n;++i)
		if(!dfn[i]) tarjan(i,_);
	return 0^_^0;
}