http://poj.org/problem?id=1515
桥输出两遍(正反)
非桥输出一遍
Description According to the Automobile Collision Monitor (ACM), most fatal traffic accidents occur on two-way streets. In order to reduce the number of fatalities caused by traffic accidents, the mayor wants to convert as many streets as possible into one-way streets. You have been hired to perform this conversion, so that from each intersection, it is possible for a motorist to drive to all the other intersections following some route. Input The input consists of a number of cases. The first line of each case contains two integers n and m. The number of intersections is n (2 <= n <= 1000), and the number of streets is m. The next m lines contain the intersections incident to each of the m streets. The intersections are numbered from 1 to n, and each street is listed once. If the pair i j is present, j i will not be present. End of input is indicated by n = m = 0. Output For each case, print the case number (starting from 1) followed by a blank line. Next, print on separate lines each street as the pair i j to indicate that the street has been assigned the direction going from intersection i to intersection j. For a street that cannot be converted into a one-way street, print both i j and j i on two different lines. The list of streets can be printed in any order. Terminate each case with a line containing a single `#' character. Sample Input Sample Output Source |
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
#define ll long long
const int maxn = 1e3 + 5;
const int maxm = 1e6 + 5;
int n, m;
int dfs_clock;
int pre[maxn], low[maxn];
struct poin
{
int from, to, next;
int w;
}G[maxm];
int head[maxn], ans = 0;
void add(int u, int v, int w)
{
G[ans].from = u;
G[ans].to = v;
G[ans].w = w;
G[ans].next = head[u];
head[u] = ans++;
}
int dfs(int u, int fa)
{
int lowu = pre[u] = ++dfs_clock;
for (int i = head[u]; ~i; i = G[i].next)
{
int v = G[i].to;
if (fa == v)continue;
if (G[i].w != -1)continue;
G[i].w = 1;
G[i ^ 1].w = 0;//0-1,2-3,4-5;神奇的配成了对!
if (!pre[v])
{
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if (lowv > pre[u]) //是桥的条件;
{
G[i ^ 1].w = 1;//就让他的另一边作标记;最后方便输出;
}
}
else if (pre[v]<pre[u] && v != fa)
{
lowu = min(lowu, pre[v]);
}
}
return low[u] = lowu;
}
int main()
{
int T = 1;
while (scanf("%d%d", &n, &m) && (n + m))
{
memset(pre, 0, sizeof(pre));
memset(low, 0, sizeof(low));
memset(head, -1, sizeof(head));
ans = 0;
for (int i = 1;i <= m;i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v, -1);
add(v, u, -1);//加双向边;
}
dfs_clock = 0;
for (int i = 1;i <= n;i++)
if (!pre[i])dfs(i, -1);//dfs一遍;
printf("%d\n\n", T++);
for (int i = 0;i < ans;i++)
{
if (G[i].w)//如果是,就输出;
{
printf("%d %d\n", G[i].from, G[i].to);//输出已经标记的边
//因为初始边已经标记过,割边标记了两次,所以会输出正反的两次
}
}
printf("#\n");
}
return 0;
}