UVA610 街的方向 题解
题目分析
一道桥的题(比模板难一点吧)。
我们要在无向图中选择一些边,使得当它们变为有向边时,该图仍能连通。
与其思考选择哪些边去改变,不如考虑哪些边不可以改。
很明显,在有向图中,如果桥变成了单向边,这幅图肯定不能连通(可结合桥的定义理解)。
那么我们只需要找出桥,也就是不能更改的边,并把他们输出两次(题目要求),则剩下的边就都可以改变,就输出一次即可。
代码实现
我们以 Tarjan 找桥的模板代码为基础,来写这道题。(为什么要用 Tarjan 找桥就不用再多说了吧。)
- 概述:很简单,是桥就不能改,不是桥就改。
- 细节:记得判重边,如果是重边直接处理下一个节点,如果不是重边且不是桥,就直接输出一遍即可。
AC 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 4005;
int T;
int n, m;
int cnt, hd[maxn];
struct node{
int to, nxt;
}e[maxn * 2];
int dfn[maxn], low[maxn];
int tmp;
void init ()
{
cnt = tmp = 0;
memset (dfn, 0, sizeof dfn);
memset (low, 0, sizeof low);
memset (e, 0, sizeof e);
memset (hd, 0, sizeof hd);
}
void add (int u, int v)
{
e[++cnt].to = v;
e[cnt].nxt = hd[u];
hd[u] = cnt;
}
void tarjan (int u, int fa)
{
int jdg = 0;
dfn[u] = low[u] = ++tmp;
for (int i = hd[u]; i; i = e[i].nxt)
{
int v = e[i].to;
jdg = 0;
if (!dfn[v])
{
tarjan (v, u);
low[u] = min (low[u], low[v]);
if (low[v] > dfn[u])
{
printf ("%d %d\n%d %d\n", u, v, v, u);
jdg = 1;
}
}
else if (dfn[v] < dfn[u] and v != fa) low[u] = min (low[u], dfn[v]);
else continue;
if (jdg == 0) printf ("%d %d\n", u, v);
}
}
int main ()
{
int T = 0;
while (1)
{
scanf ("%d %d", &n, &m);
if(!n and !m) break;
init ();
for (int i = m; i > 0; i--)
{
int u, v;
scanf ("%d %d", &u, &v);
add (u, v), add (v, u);
}
cout << ++T << endl << endl;
for (int i = 1; i <= n; i++)
{
if (!dfn[i]) tarjan (i, -1);
}
cout << "#" << endl;
}
return 0;
}

浙公网安备 33010602011771号