题解【洛谷P1656】炸铁路

题面

题目其实就是要找出图中所有的割边(桥)。

于是直接 Tarjan 即可。

输出时记得还要排序。

#include <bits/stdc++.h>

using namespace std;

inline int gi()
{
    int f = 1, x = 0; char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return f * x;
}

const int INF = 0x3f3f3f3f, N = 153, M = 10003;

int n, m;
int tot = 1, head[N], ver[M], nxt[M];
int dfn[N], low[N], tim;
int cnt;
struct Node
{
	int u, v;
} a[M];

inline void add(int u, int v)
{
	ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}

void Tarjan(int u, int fa)
{
	dfn[u] = low[u] = ++tim;
	for (int i = head[u]; i; i = nxt[i])
	{
		int v = ver[i];
		if (!dfn[v])
		{
			Tarjan(v, i);
			low[u] = min(low[u], low[v]);
			if (low[v] > dfn[u])
				a[++cnt] = (Node){u, v};
		}
		else if (i != (fa ^ 1)) low[u] = min(low[u], dfn[v]);
	}
}

inline bool cmp(Node x, Node y)
{
	if (x.u != y.u) return x.u < y.u;
	return x.v < y.v;
}

int main()
{
    n = gi(), m = gi();
    for (int i = 1; i <= m; i+=1)
    {
    	int u = gi(), v = gi();
    	add(u, v), add(v, u);
    }
    for (int i = 1; i <= n; i+=1)
    	if (!dfn[i]) Tarjan(i, i);
    sort(a + 1, a + 1 + cnt, cmp);
    for (int i = 1; i <= cnt; i+=1) 
    	printf("%d %d
", a[i].u, a[i].v);
    return 0;
}
原文地址:https://www.cnblogs.com/xsl19/p/13046554.html