luogu P3388 【模板】割点(割顶)
题目背景
割点
题目描述
给出一个n个点,m条边的无向图,求图的割点。
输入输出格式
输入格式:
第一行输入n,m
下面m行每行输入x,y表示x到y有一条边
输出格式:
第一行输出割点个数
第二行按照节点编号从小到大输出节点,用空格隔开
输入输出样例
说明
n,m均为100000
tarjan 图不一定联通!!!
#include<cstdio> #include<algorithm> using namespace std; inline int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-')f=-1; c=getchar(); } while(c<='9'&&c>='0') { x=x*10+c-'0'; c=getchar(); } return x*f; } const int maxn = 100007; int low[maxn],dfn[maxn],head[maxn]; struct node{ int v,next; }edge[maxn*2];int num,tn; bool iscut[maxn]; inline void add_edge(int u,int v) { edge[++num].v=v;edge[num].next=head[u];head[u]=num; } int ans=0; void tarjan(int u,int fa) { low[u] = dfn[u] = ++tn; int cnt_son = 0; for (int i=head[u]; i; i=edge[i].next) { int v = edge[i].v; if (!dfn[v]) { cnt_son++; tarjan(v,u); low[u]=min(low[u],low[v]); if (low[v]>=dfn[u]) if(!iscut[u]) iscut[u]=true,ans++; } else if(dfn[v]<dfn[u]&&v!=fa) low[u]=min(low[u],dfn[v]); } if(fa<0&&cnt_son==1) iscut[u]=false,ans--; } int main() { //while(1){}; int n=read(),m=read(); for(int a,b,i=1;i<=m;++i) { a=read(),b=read(); add_edge(a,b); add_edge(b,a); } for(int i=1;i<=n;++i) if(!dfn[i])tarjan(i,-1); printf("%d\n",ans); int qq=0; for(int i=1;i<=n;++i) { if(iscut[i])printf("%d ",i); } return 0; }