Tarjan边双连通分量【模板】

#include <bits/stdc++.h>
#define int long long
typedef std::pair<int, int> pii;
const int N = 2e5 + 5, M = 6e5 + 5;
int n, m;
int dfn[N], low[N], tim;
int id[N], siz[N], bcc_cnt;
std::stack<int> st;
bool is_bridge[M];
std::vector<pii> answer;//记录边(转化成了有向边)
struct Edge
{
	int to, next;
} edge[M];
int head[N], cnt;
void add_edge(int u, int v)
{
	edge[cnt].to = v;
	edge[cnt].next = head[u];
	head[u] = cnt++;
}
void tarjan(int u, int fu)
{
	dfn[u] = low[u] = ++tim;
	st.push(u);
	for (int i = head[u]; i != -1; i = edge[i].next)
	{
		int j = edge[i].to;
		if (!dfn[j])
		{
			tarjan(j, i);
			answer.push_back({u, j});
			low[u] = std::min(low[u], low[j]);
			if (dfn[u] < low[j])
			{
				is_bridge[i] = is_bridge[i ^ 1] = true;
			}
		}
		else if (i != (fu ^ 1))
		{
			low[u] = std::min(low[u], dfn[j]);
			if (dfn[j] < dfn[u])
			{
				answer.push_back({u, j});
			}
		}
	}
	if (dfn[u] == low[u])
	{
		++bcc_cnt;
		int k;
		do
		{
			k = st.top();
			st.pop();
		} while (k != u);
	}
}
void solve()
{
	memset(head, -1, sizeof head);
	std::cin >> n >> m;
	for (int i = 1, a, b; i <= m; i++)
	{
		std::cin >> a >> b;
		add_edge(a, b);
		add_edge(b, a);
	}
	tarjan(1, -1);
	if (bcc_cnt > 1)
	{
		std::cout << 0 << std::endl;
		return;
	}
	for (pii val : answer)
	{
		std::cout << val.first << " " << val.second << std::endl;
	}
}
signed main()
{
	std::ios::sync_with_stdio(false);
	std::cin.tie(0), std::cout.tie(0);
	int T = 1;
	// std::cin >> T;
	for (int i = 1; i <= T; i++)
	{
		solve();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值