UOJ#67 新年的毒瘤 tarjan

题目传送门

题意:给出一个$N$个点、$M$条边的无向图,找出其中的点,满足去掉该点与和它相连的边之后,这个图会变成一棵树。$N , M \leq 10^5$


说是毒瘤,真的不毒瘤

思考一下,我们需要找的就是度为$M - (N - 1 - 1)$且不是割点的点,直接tarjan即可

想起来在某luogu题解里把tarjan写成targan

 1 #include<bits/stdc++.h>
 2 #define MAXN 100001
 3 using namespace std;
 4 
 5 inline int read(){
 6     int a = 0;
 7     char c = getchar();
 8     while(!isdigit(c))
 9         c = getchar();
10     while(isdigit(c)){
11         a = (a << 3) + (a << 1) + (c ^ '0');
12         c = getchar();
13     }
14     return a;
15 }
16 
17 struct Edge{
18     int end , upEd;
19 }Ed[MAXN << 1];
20 
21 int head[MAXN] , dfn[MAXN] , low[MAXN] , in[MAXN] , ts , cntEd , N , M;
22 bool vis[MAXN];
23 
24 inline void addEd(int a , int b){
25     Ed[++cntEd].end = b;
26     Ed[cntEd].upEd = head[a];
27     head[a] = cntEd;
28     in[a]++;
29 }
30 
31 void tarjan(int a , int fa){
32     dfn[a] = low[a] = ++ts;
33     int ch = 0;
34     for(int i = head[a] ; i ; i = Ed[i].upEd)
35         if(Ed[i].end != fa)
36             if(!dfn[Ed[i].end]){
37                 tarjan(Ed[i].end , a);
38                 low[a] = min(low[Ed[i].end] , low[a]);
39                 ch++;
40                 if(low[Ed[i].end] >= dfn[a] && a != 1)
41                     vis[a] = 1;
42             }
43             else
44                 low[a] = min(low[a] , dfn[Ed[i].end]);
45     if(a == 1 && ch >= 2)
46         vis[a] = 1;
47 }
48 
49 int main(){
50     N = read();
51     M = read();
52     for(int i = 1 ; i <= M ; i++){
53         int a = read() , b = read();
54         addEd(a , b);
55         addEd(b , a);
56     }
57     tarjan(1 , 0);
58     int ans = 0;
59     for(int i = 1 ; i <= N ; i++)
60         if(in[i] == M - N + 2 && !vis[i])
61             ans++;
62     cout << ans << endl;
63     for(int i = 1 ; i <= N ; i++)
64         if(in[i] == M - N + 2 && !vis[i])
65             cout << i << ' ';
66     return 0;
67 }

猜你喜欢

转载自www.cnblogs.com/Itst/p/9783948.html