1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <vector>
5
6 using namespace std;
7 #define MAXN 1000
8 int low[MAXN],visit[MAXN]; // low[i] = min(visit[i],visist[j],low[w]); j 是 回路的父值,w是儿子值
9 int pointNum,edgeNum;
10 int count; // 统计遍历的顺序
11
12 int dfsArticul(vector<vector<int> > G,int v0) { // 最小的low[]值
13 int min = visit[v0] = ++count;
14 for (int i = 0;i < G[v0].size();i++) {
15 int w = G[v0][i];
16 if (visit[w] == 0) {
17 low[w] = dfsArticul(G,w);
18 if (low[w] < min) min = low[w];
19 if (low[w] >= visit[v0]) cout << v0 << endl;
20 }
21 else if (visit[w] < min) {
22 min = visit[w];
23 }
24 }
25 return low[v0] = min;
26 }
27
28 void findArticul(vector <vector<int> > G) {
29 visit[0] = 1;
30 count = 1;
31 for (int i = 1;i < pointNum;i++) {
32 visit[i] = 0;
33 }
34 int p = G[0][0];
35 dfsArticul(G,p);
36 if (count < pointNum) { // 父节点是否有两个子树
37 cout << 0 << endl;
38 for (int i = 1;i < G[0].size();i++) {
39 int w = G[0][i];
40 if (visit[w] == 0)
41 dfsArticul(G,w);
42 }
43 }
44 }
45
46 int main () {
47 // freopen("1.in","r",stdin);
48 vector <vector<int> > G; // 邻接表
49 cin >> pointNum >> edgeNum; // 点的个数,边的个数
50 G.resize(pointNum + 1);
51 for (int i = 0;i < pointNum;i++) G[i].clear();
52 for (int i = 0;i < edgeNum;i++) {
53 int x,y;
54 cin >> x >> y; // 边的起点,和终点
55 G[x].push_back(y);
56 G[y].push_back(x);
57 }
58 findArticul(G);
59 }