tarjan求边双点双连通分量

边双 Code

#include<bits/stdc++.h>
using namespace std;
const int maxm=5000010;
int n,m;
int h[maxm],to[maxm],nxt[maxm],tot;
int dfn[maxm],low[maxm],num;
bool bridge[maxm];
int zhan[maxm],top,cnt;
vector<int> dccc[maxm];
void add(int x,int y)
{
	tot++;
	to[tot]=y;
	nxt[tot]=h[x];
	h[x]=tot;
}
void tarjan(int x,int edge)
{
	num++;
	dfn[x]=low[x]=num;
	zhan[++top]=x;
	for (int i=h[x];i;i=nxt[i])
	{
		int y=to[i];
		if (!dfn[y])
		{
			tarjan(y,i);
			low[x]=min(low[x],low[y]);
			if (dfn[x]<low[y])
			{
				bridge[i]=bridge[i^1]=true;
			}
		}
		else if (i!=(edge^1))
		{
			low[x]=min(low[x],dfn[y]);
		}
	}
	if (dfn[x] == low[x])
	{
		cnt++;
		int z;
		do
		{
			z = zhan[top];
			top--;
			dccc[cnt].push_back(z);
			//if(z == x) break;
		}while (z!=x);
	}
}
int main()
{
	int x,y;
	tot=1;
	cin >> n >> m;
	for (int i=1;i<=m;i++)
	{
		cin >> x >> y;
		add(x,y);
		add(y,x);
	}
	for (int i=1;i<=n;i++)
	{
		if (!dfn[i]) tarjan(i,0);
	}
	cout << cnt << endl;
	for (int i=1;i<=cnt;i++)
	{
		cout << dccc[i].size() << " ";
		for (int l : dccc[i]) cout << l << " ";
		cout << endl;
	}
	return 0;
}

点双Code

#include<bits/stdc++.h>
using namespace std;
const int maxm=5000010;
int n,m;
int h[maxm],to[maxm],nxt[maxm],tot;
int dfn[maxm],low[maxm],num;
int root;
bool cut[maxm];
int zhan[maxm],top,cnt;
vector<int> dcc[maxm];
void add(int x,int y)
{
	tot++;
	to[tot]=y;
	nxt[tot]=h[x];
	h[x]=tot;
}
void tarjan(int x)
{
	num++;
	dfn[x]=low[x]=num;
	zhan[++top]=x;
	if (x == root && h[x] == 0)// 孤点
	{
		dcc[++cnt].push_back(x);
		return;
	}
	int flag=0;
	for (int i=h[x];i;i=nxt[i])
	{
		int y=to[i];
		if (!dfn[y])
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if (dfn[x]<=low[y])
			{
				flag++;
				if (x!=root || flag>1) cut[x]=true;
				cnt++;
				int z=0;
				do
				{
					z=zhan[top--];
					dcc[cnt].push_back(z);
				}while (z!=y);
				dcc[cnt].push_back(x);
			}
		}
		else
		{
			low[x]=min(low[x],dfn[y]);
		}
	}
}
int main()
{
	int x,y;
	cin >> n >> m;
	for (int i=1;i<=m;i++)
	{
		cin >> x >> y;
		if (x == y) continue;
		add(x,y);
		add(y,x);
	}
	for (int i=1;i<=n;i++)
	{
		if (!dfn[i])
		{
			root=i;
			tarjan(i);
		}
	}
	cout << cnt << endl;
	for (int i=1;i<=cnt;i++)
	{
		cout << dcc[i].size() << " ";
		for (int l : dcc[i]) cout << l << " ";
		cout << endl;
	}
	
	return 0;
}
posted @ 2026-03-24 11:46  msjing  阅读(12)  评论(0)    收藏  举报