割点

【模板】割点(割顶)

时空限制3000ms / 128MB

题目背景

割点

题目描述

给出一个n个点,m条边的无向图,求图的割点。

输入输出格式

输入格式:

第一行输入n,m

下面m行每行输入x,y表示x到y有一条边

输出格式:

第一行输出割点个数

第二行按照节点编号从小到大输出节点,用空格隔开

输入输出样例

输入样例: 
6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6
输出样例: 
1 
5

说明

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;
}
View Code
原文地址:https://www.cnblogs.com/tian-luo/p/9582184.html