1 //无向图求割边
2 #include <cstdio>
3 #include <cstdlib>
4 #include <cstring>
5 #include <cmath>
6 #include <algorithm>
7 #include <queue>
8 #include <stack>
9 #include <vector>
10 #include <deque>
11 #include <map>
12 #include <iostream>
13 using namespace std;
14 typedef long long LL;
15 const double pi = acos(-1.0);
16 const double e = exp(1);
17 //const int MAXN =2e5+10;
18 const LL N = 1000000007;
19
20 struct edge{
21 int w;
22 int to;
23 int next;
24 }edge[200009];
25 int head[200009];
26
27 int dfn[100009];
28 int low[100009];
29 int cnt = 1;
30
31 void tarjan(int u, int fa)
32 {
33
34 int i;
35 low[u] = dfn[u] = cnt++;
36 for(i = head[u]; i != -1; i = edge[i].next)
37 {
38 //cout << u << " " << fa << endl;
39 int v = edge[i].to;
40 if(!dfn[v])
41 {
42 //cout << "** " << v << " " << u << endl;
43 tarjan(v, u);
44 low[u] = min(low[u], low[v]);
45 if(low[v] > dfn[u])
46 {
47 printf("%d ---> %d\n", u, v);
48 }
49 }
50 else if(v != fa)
51 {
52 low[u] = min(low[u], dfn[v]);
53 }
54 }
55 }
56
57 int main()
58 {
59 int n,m, i;
60 int cnt1, a, b;
61 while(scanf("%d%d", &n,&m) != EOF)
62 {
63 if(n == 0 && m == 0)
64 break;
65 cnt1 = 0;
66 cnt = 1;
67 memset(head, -1, sizeof(head));
68 memset(dfn, 0, sizeof(dfn));
69 memset(low, 0, sizeof(low));
70 while(m--)
71 {
72 scanf("%d%d", &a,&b);
73
74 edge[cnt1].to = b;
75 edge[cnt1].next = head[a];
76 head[a] = cnt1++;
77
78 edge[cnt1].to = a;
79 edge[cnt1].next = head[b];
80 head[b] = cnt1++;
81 }
82 for(i = 1; i <= n; i++)
83 {
84 if(!dfn[i])
85 {
86 tarjan(i, 0);
87 }
88 }
89
90 }
91 return 0;
92 }