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 }