题目背景
割点
题目描述
给出一个nn个点,mm条边的无向图,求图的割点。
输入格式
第一行输入n,mn,m
下面mm行每行输入x,yx,y表示xx到yy有一条边
输出格式
第一行输出割点个数
第二行按照节点编号从小到大输出节点,用空格隔开
输入输出样例
输入 #1
6 7 1 2 1 3 1 4 2 5 3 5 4 5 5 6
输出 #1
1 5
说明/提示
对于全部数据,n \le 20000n≤20000,m \le 100000m≤100000
点的编号均大于00小于等于nn。
tarjan图不一定联通。
套用Tarjan模板:
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
#define lowbit(x) (x&-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define INF 999999
#define MAXN 20005
//struct edge{
// int to;
// //int val;
//};
//int next[MAXN];
vector<int> G[MAXN];
int dfn[MAXN],low[MAXN];
bool instack[MAXN];
set<int> ans; //存储割点
//stack<int> s;
int timing; //时间戳
int color[MAXN]; //代表当前结点所属第几个scc
int colorcnt[MAXN]; //代表第某个scc有几个结点
int cnt; //scc个数
int V,E;
void init()
{
for(int i=0;i<=V;i++)
G[i].clear();
ans.clear();
mem(dfn,0);
mem(color,0);
mem(colorcnt,0);
mem(instack,false);
mem(low,0);
timing=cnt=0;
}
//割点
void tarjan(int u,int rt)
{
++timing;
low[u]=dfn[u]=timing;
int child=0;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(dfn[v]==0)
{
child++;
tarjan(v,rt);
low[u]=min(low[u],low[v]);
if(u!=rt && low[v]>=dfn[u]){
ans.insert(u);
}
}
low[u]=min(low[u],dfn[v]);
}
if(child>=2&&u==rt){
ans.insert(u);
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> V >> E;
int x,y;
for(int i=1;i<=E;i++)
{
cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1;i<=V;i++){
if(dfn[i]==0)
tarjan(i,i);
}
cout << ans.size() << endl;
set<int>::iterator ite;
for(ite=ans.begin();ite!=ans.end();ite++)
cout << *ite << " ";
cout << endl;
return 0;
}