P3388 【模板】割点(割顶)

题目链接:https://www.luogu.com.cn/problem/P3388

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1e5+10;//注意如按照题目给定的最大n会出现RE情况 
 7 const int maxm=2e5+10;
 8 int n, m;
 9 struct edge{
10     int to, next;
11 }e[maxm];
12 int head[maxn], tot;
13 void add(int u, int v){
14     e[++tot].to=v;
15     e[tot].next=head[u];
16     head[u]=tot;
17 }
18 
19 int ans[maxn];//存放答案 
20 
21 int dfs[maxn], low[maxn], num;//时间戳、追溯点 
22 int root; //记录根节点 
23 void tarjan(int u, int fa){
24     dfs[u]=low[u]=++num;
25     int child=0;//计数多少个儿子 
26     for(int i=head[u]; i; i=e[i].next){
27         int v=e[i].to;
28         if(v==fa)//v是u的父亲 
29             continue;
30         if(!dfs[v]){//未赋值,未访问
31             tarjan(v, u);
32             low[u]=min(low[u], low[v]);
33             if(low[v]>=dfs[u]){
34                 child++;
35                 if(u!=root || child>1)//不是根 或者 是根且有两个以上满足 
36                     ans[u]=1;//存到答案数组 
37             }
38         }
39         else
40             low[u]=min(low[u], dfs[v]);//注意此处代码的理解 
41     }
42 }
43 int main()
44 {
45     scanf("%d%d",&n, &m);
46     while(m--){
47         int x, y;
48         scanf("%d%d", &x, &y);
49         add(x, y); add(y, x);
50     }
51     for(int i=1; i<=n; i++){
52         if(!dfs[i]){
53             root=i;        
54             tarjan(i, 0);
55         }    
56     }
57     
58     int tot=0;
59     for(int i=1; i<=n; i++)
60         if(ans[i])tot++;
61     printf("%d\n", tot);
62     for(int i=1; i<=n; i++)
63         if(ans[i])
64             printf("%d ", i);
65     return 0;
66 }

 

posted @ 2022-04-24 23:12  TFLSNOI  阅读(48)  评论(0编辑  收藏  举报