tarjan求割点割边

Code 割点

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const int maxm=1000010;
int n,m;
int h[maxn],to[maxm],nxt[maxm],tot;
int dfn[maxn],low[maxn],num;
int root;
bool cut[maxn];
int ans[maxm];
int cnt;
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;
	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) // 不是根或多个子节点 
				{
					if (!cut[x])
					{
						cut[x]=true;
						cnt++;
					}
				}
			}
		}
		else low[x]=min(low[x],dfn[y]);
	}
}
int main()
{
	int x,y;
	cin >> n;
	while (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);
		}
	}
	int num=0;
	for (int i=1;i<=n;i++)
	{
		if (cut[i]) ans[++num]=i;
	}
	if (num == 0) cout << "0" << endl;
	else
	{
		cout << num << endl;
		for (int i=1;i<=num;i++) cout << ans[i] << endl;
	}
	return 0;
}

Code 割边

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const int maxm=1000010;
int n,m;
int h[maxn],to[maxm],nxt[maxm],tot;
int dfn[maxn],low[maxn],num;
bool bridge[maxm];
int sum;
struct node
{
	int l,r;
}ans[maxm];
bool cmp (node nd1,node nd2)
{
	if (nd1.l == nd2.l) return nd1.r<nd2.r;
	else return nd1.l<nd2.l;
}
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;
	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]) // panduan qwq
			{
				bridge[i]=bridge[i^1]=true;
			}
		}
		//i == (edge ^ 1)表示与i是同一条边
		//i != (edge ^ 1)说明是非树边
		else if (i!=(edge^1))
		{
			low[x]=min(low[x],dfn[y]);
		}
	}
}
int main()
{
	int x,y;
	tot=1; // 使编号从2开始,以防^出0来
	cin >> n >> m;
	while (m--)
	{
		cin >> x >> y;
		add(x,y);
		add(y,x);
	}
	for (int i=1;i<=n;i++)
	{
		if (!dfn[i]) tarjan(i,0);
	}
	for (int i=2;i<tot;i++)
	{
		if (bridge[i])
		{
			sum++;
			ans[sum].l = to[i^1];
			ans[sum].r = to[i];
			if (ans[sum].l>ans[sum].r) swap(ans[sum].l,ans[sum].r);
		}
	}
	sort(ans+1,ans+1+sum,cmp);
	for (int i=1;i<=sum;i++)
	{
		if (ans[i].l == ans[i-1].l && ans[i].r == ans[i-1].r) continue;
		cout << ans[i].l << " " << ans[i].r << endl;
	}
	return 0;
}
posted @ 2026-03-24 11:46  msjing  阅读(7)  评论(0)    收藏  举报