P3388 【模板】割点(割顶)
P3388 【模板】割点(割顶)
题目背景
割点
题目描述
给出一个n个点,m条边的无向图,求图的割点。
输入输出格式
输入格式:
第一行输入n,m
下面m行每行输入x,y表示x到y有一条边
输出格式:
第一行输出割点个数
第二行按照节点编号从小到大输出节点,用空格隔开
输入输出样例
说明
n,m均为100000
tarjan 图不一定联通!!!
分析
tarjan求割点
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 7 using namespace std; 8 9 const int N = 100100; 10 struct Edge{ 11 int to,nxt; 12 }e[N<<1]; 13 int head[N],dfn[N],low[N]; 14 bool iscut[N]; 15 int tn,tot; 16 17 inline char nc() { 18 static char buf[100000],*p1 = buf,*p2 = buf; 19 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++; 20 } 21 inline int read() { 22 int x = 0,f = 1;char ch = nc(); 23 for (; ch<'0'||ch>'9'; ch = nc()) 24 if (ch=='-') f = -1; 25 for (; ch>='0'&&ch<='9'; ch = nc()) 26 x = x*10+ch-'0'; 27 return x * f; 28 } 29 30 void add_edge(int u,int v) { 31 e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot; 32 } 33 34 void tarjan(int u,int fa) { 35 low[u] = dfn[u] = ++tn; 36 int cnt_son = 0; 37 for (int i=head[u]; i; i=e[i].nxt) { 38 int v = e[i].to; 39 if (!dfn[v]) { 40 cnt_son++; 41 tarjan(v,u); 42 low[u] = min(low[u],low[v]); 43 if (low[v] >= dfn[u]) 44 iscut[u] = true; 45 } 46 else if (dfn[v] < dfn[u] && v != fa) 47 low[u] = min(low[u],dfn[v]); 48 } 49 if (fa<0 && cnt_son==1) iscut[u] = false; 50 } 51 int main() { 52 int n = read(),m = read(); 53 for (int u,v,i=1; i<=m; ++i) { 54 u = read(),v = read(); 55 add_edge(u,v),add_edge(v,u); 56 } 57 for (int i=1; i<=n; ++i) 58 if (!dfn[i]) tarjan(i,-1); 59 60 int ans = 0; 61 for (int i=1; i<=n; ++i) 62 if (iscut[i]) ans++; 63 printf("%d\n",ans); 64 for (int i=1; i<=n; ++i) 65 if (iscut[i]) printf("%d ",i); 66 return 0; 67 }