日常tarjan
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int maxn=1000010; 6 struct edge{ 7 int to, next; 8 }a[maxn*2]; 9 int head[maxn], cnt=0; 10 int dfn[maxn], low[maxn], num=0; 11 bool cut[maxn]; 12 int n, m, tot=0; 13 void add(int u, int v){ 14 cnt++; 15 a[cnt].to=v; 16 a[cnt].next=head[u]; 17 head[u]=cnt; 18 } 19 void tarjan(int u, int fa){ 20 dfn[u]=low[u]=++num; 21 int child=0; 22 for(int i=head[u]; i; i=a[i].next){ 23 int v=a[i].to; 24 if(dfn[v]){ 25 tarjan(v, fa); 26 low[u]=min(low[u],low[v]); 27 if(low[v]>=dfn[u] && u!=fa) cut[u]=true; 28 // 非根节点如果 low[v]>=dfn[u]即为割点 29 if(u==fa) child++;//统计子树 30 } 31 low[u]=min(low[u],dfn[v]); 32 } 33 if(child>=2 && u==fa) cut[u]=true; 34 //对于根节点来说,如果有两颗以上的子树,就是割点 35 //因为去掉之后两棵子树不能互达 36 } 37 int main(){ 38 memset(dfn,0,sizeof(dfn)); 39 memset(head,0,sizeof(head)); 40 scanf("%d%d",&n,&m); 41 for(int i=1; i<=m; i++){ 42 int a, b; 43 scanf("%d%d",&a,&b); 44 add(a, b); 45 add(b, a); 46 } 47 for(int i=1; i<=n; i++) 48 if(!dfn[i]) tarjan(i, i); 49 for(int i=1; i<=n; i++) 50 if(cut[i]) tot++; 51 printf("%d ",tot); 52 for(int i=1; i<=n; i++) 53 if(cut[i]) printf("%d ",i); 54 return 0; 55 }