洛谷P3388 【模板】割点(割顶)
题目背景
割点
题目描述
给出一个n个点,m条边的无向图,求图的割点。
输入输出格式
输入格式:
第一行输入n,m
下面m行每行输入x,y表示x到y有一条边
输出格式:
第一行输出割点个数
第二行按照节点编号从小到大输出节点,用空格隔开
输入输出样例
说明
对于全部数据,n≤20000,m≤100000
点的编号均大于0小于等于n。
tarjan图不一定联通。
1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 long long read() 7 { 8 long long x=0,f=1; 9 char ch=getchar(); 10 while(ch>'9'||ch<'0') 11 { 12 if(ch=='-') 13 f=-1; 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') 17 { 18 x=x*10+ch-'0'; 19 ch=getchar(); 20 } 21 return x*f; 22 } 23 const int maxn=100005; 24 int n,m,num,cnt,ans; 25 int fa[maxn],low[maxn],head[maxn],dfn[maxn]; 26 struct edge 27 { 28 int u,v,nxt; 29 } e[maxn<<1]; 30 bool cut[maxn]; 31 inline void add(int u,int v) 32 { 33 e[++num].u=u; 34 e[num].v=v; 35 e[num].nxt=head[u]; 36 head[u]=num; 37 } 38 void tarjan(int x) 39 { 40 int in=0; 41 dfn[x]=low[x]=++cnt; 42 for(int v,i=head[x]; i; i=e[i].nxt) 43 { 44 v=e[i].v; 45 if(!dfn[v]) 46 { 47 fa[v]=fa[x]; 48 tarjan(v); 49 low[x]=fmin(low[x],low[v]); 50 if(low[v]>=dfn[x]&&x!=fa[x]) 51 cut[x]=true; 52 if(x==fa[x]) 53 ++in; 54 } 55 low[x]=fmin(low[x],dfn[v]); 56 } 57 if(x==fa[x]&&in>=2) 58 cut[fa[x]]=true; 59 } 60 int main() 61 { 62 n=read(),m=read(); 63 for(int i=1; i<=n; ++i) 64 fa[i]=i; 65 for(int i=1; i<=m; ++i) 66 { 67 int u,v; 68 u=read(),v=read(); 69 add(u,v); 70 add(v,u); 71 } 72 for(int i=1; i<=n; ++i) 73 if(!dfn[i]) 74 tarjan(i); 75 for(int i=1; i<=n; ++i) 76 if(cut[i]) 77 ++ans; 78 printf("%d\n",ans); 79 for(int i=1; i<=n; ++i) 80 if(cut[i]) 81 printf("%d ",i); 82 return 0; 83 }