时空限制3000ms / 128MB
题目背景
割点
题目描述
给出一个n个点,m条边的无向图,求图的割点。
输入输出格式
输入格式:第一行输入n,m
下面m行每行输入x,y表示x到y有一条边
输出格式:第一行输出割点个数
第二行按照节点编号从小到大输出节点,用空格隔开
输入输出样例
说明
n,m均为100000
tarjan图不一定联通!!!
点的编号均大于0小于等于n
tarjan求割点裸题。
#include<bits/stdc++.h> #define N 200050 using namespace std; vector<int>edges[N]; int dfn[N]={0},low[N]={0}; int addblock[N]={0}; int now_clo; void dfs(int x,int pre) { dfn[x]=low[x]=now_clo++; int son=0; for(int i=0;i<edges[x].size();i++) if(edges[x][i]!=pre) { if(!dfn[edges[x][i]]) { son++; dfs(edges[x][i],x); low[x]=min(low[x],low[edges[x][i]]); if(pre!=-1&&low[edges[x][i]]>=dfn[x])addblock[x]++; } else low[x]=min(low[x],dfn[edges[x][i]]); } if(pre==-1)addblock[x]=son-1; } int main() { int n,m,x,y; scanf("%d %d",&n,&m); while(m--) { scanf("%d %d",&x,&y); edges[x].push_back(y); edges[y].push_back(x); } for(int i=1;i<=n;i++)if(!dfn[i])now_clo=1,dfs(i,-1); int sum=0; for(int i=1;i<=n;i++)if(addblock[i]>0)sum++;//如果根是单个结点,addblock就会是负值 printf("%d ",sum); for(int i=1;i<=n;i++)if(addblock[i]>0)printf("%d ",i); return 0; }