cychester

UOJ 67 新年的毒瘤 - Tarjan

Description

给出一个无向图, 要求找出某个点$u$, 去掉$u$和$u$所连的边, 所剩下的节点构成一棵树。

Solution

首先, 割点肯定是不可能满足条件的, 因为去掉割点后会构成若干个不连通的图。

所以我们先求出割点, 再查找不是割点, 并且 去掉它连接的边, 剩下的 边数为$N-2$, 只有这种点才能够满足要求。

 

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #define rd read()
 6 using namespace std;
 7 
 8 const int N = 1e5 + 5;
 9 
10 int head[N], tot;
11 int low[N], dfn[N], cnt, cut[N], d[N];
12 int n, m;
13 
14 vector<int> q;
15 
16 struct edge {
17     int nxt, to;
18 }e[N << 1];
19 
20 int read() {
21     int X = 0, p = 1; char c = getchar();
22     for (; c > '9' || c < '0'; c = getchar()) if (c == '-') p = -1;
23     for (; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
24     return X * p;
25 }
26 
27 void add(int u, int v) {
28     e[++tot].to = v;
29     e[tot].nxt = head[u];
30     head[u] = tot;
31 }
32 
33 void tarjan(int u) {
34     low[u] = dfn[u] = ++cnt;
35     int flag = 0;
36     for (int i = head[u]; i; i = e[i].nxt) {
37         int nt = e[i].to;
38         if (!dfn[nt]) {
39             tarjan(nt);
40             low[u] = min(low[u], low[nt]);
41             if (low[nt] >= dfn[u]) {
42                 flag ++;
43                 if (flag > 1 || u - 1)
44                     cut[u] = 1;
45             }
46         }
47         else low[u] = min(low[u], dfn[nt]);
48     }
49 }
50 
51 int main()
52 {
53     n = rd; m = rd;
54     for (int i = 1; i <= m; ++i) {
55         int u = rd, v = rd;
56         add(u, v); add(v, u);
57         d[u]++; d[v]++;
58     }
59     tarjan(1);
60     for (int i = 1; i <= n; ++i)
61         if (!cut[i] && m - d[i] == n - 2)
62             q.push_back(i);
63     printf("%d\n", (int)q.size());
64     for (int i = 0, len = q.size(); i < len; ++i)
65         printf("%d ", q[i]);
66     puts("");
67 }
View Code

 

posted on 2018-09-18 13:42  cychester  阅读(151)  评论(0编辑  收藏  举报

导航