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 }