题目描述
给出一个n个点,m条边的无向图,求图的割点。
题目解析
割点判定条件:
x == from时:子树个数>1
x != from时:low[l[i].to] >= dfn[x]
Code
#include<iostream> #include<cstdio> using namespace std; const int MAXN = 20000 + 5; const int MAXM = 100000 + 5; struct Edge { int nxt; int to; } l[MAXM<<1]; int n,m,ans; int head[MAXN],cnt; int low[MAXN],dfn[MAXN],stamp; int stack[MAXN],top; bool cut[MAXN]; inline int rd() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?-1:1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } inline void add(int x,int y) { cnt++; l[cnt].nxt = head[x]; l[cnt].to = y; head[x] = cnt; return; } void tarjan(int x,int from) { low[x] = dfn[x] = ++stamp; int son = 0; for(int i = head[x];i;i = l[i].nxt) { if(!dfn[l[i].to]) { tarjan(l[i].to,x); low[x] = min(low[x],low[l[i].to]); if(low[l[i].to] >= dfn[x] && x != from) cut[x] = true; if(x == from) son++; } low[x] = min(low[x],dfn[l[i].to]); } if(son > 1 && x == from) cut[x] = true; return; } int main() { scanf("%d%d",&n,&m); int x,y; for(register int i = 1;i <= m;i++) { x = rd(), y = rd(); add(x,y), add(y,x); } for(register int i = 1;i <= n;i++) { if(!dfn[i]) tarjan(i,i); } for(register int i = 1;i <= n;i++) ans += cut[i]; printf("%d ",ans); for(int i = 1;i <= n;i++) { if(cut[i]) printf("%d ",i); } return 0; }