割點node
給出一個n個點,m條邊的無向圖,求圖的割點。c++
輸入格式:spa
第一行輸入n,mblog
下面m行每行輸入x,y表示x到y有一條邊it
輸出格式:io
第一行輸出割點個數class
第二行按照節點編號從小到大輸出節點,用空格隔開im
n,m均爲100000di
tarjan圖不必定聯通!!!vi
點的編號均大於0小於等於n
#include <bits/stdc++.h> using namespace std; using ll=long long; const int MAXN=1e5+10; struct node{ int v; int Next; }edge[MAXN<<1 ]; int head[MAXN], cnt,low[MAXN],dfn[MAXN],Time; bool vis[MAXN]; void add(int u,int v) { edge[++cnt].v=v; edge[cnt].Next=head[u]; head[u]=cnt; } void tarjan(int u,int fa) { dfn[u]=low[u]=++Time; int child=0; for (int i = head[u]; i !=-1 ; i=edge[i].Next) { int v=edge[i].v; if(!dfn[v]) { //沒有被訪問過。 tarjan(v,fa); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]&&u!=fa)//一個點能鏈接到最遠的祖先節點仍大於或者等於他的父親節點,那麼他的父親節點必定是割點 vis[u]=1; if(u==fa) child++; } low[u]=min(low[u],dfn[v]);//求割點時只能是dfn[v],強連通份量能夠是dfn[v]||low[v] } if(child>=2&&u==fa) vis[u]=1; } int main() { int n,m; scanf("%d%d",&n,&m); memset(head,-1, sizeof(head)); int u,v; for (int i = 0; i <m ; ++i) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for (int i = 1; i <=n ; ++i) { if(!dfn[i]) tarjan(i,i); } int sum=0; for (int i = 1; i <=n ; ++i) { if(vis[i]) sum++; } printf("%d\n",sum); for (int i = 1; i <=n ; ++i) { if(vis[i]) printf("%d ",i); } return 0; }