洛谷P3388 【模板】割点(割顶)

P3388 【模板】割点(割顶)

题目背景

割点

题目描述

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

输入输出格式

输入格式:

 

第一行输入n,m

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

 

输出格式:

 

第一行输出割点个数

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

 

输入输出样例

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

说明

n,m均为100000

tarjan 图不一定联通!!!

#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 100010
using namespace std;
int dfn[maxn],low[maxn],cnt,ans;
bool cut[maxn];
int n,m,num,head[maxn];
struct node{
    int from,to,pre;
}e[maxn*2];
void Insert(int from,int to){
    e[++num].to=to;
    e[num].from=from;
    e[num].pre=head[from];
    head[from]=num;
}
void Tarjan(int u,int father){
    int rc=0;
    cnt++;dfn[u]=low[u]=cnt;
    for(int i=head[u];i;i=e[i].pre){
        int v=e[i].to;
        if(!dfn[v]){
            Tarjan(v,father);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]&&u!=father)cut[u]=1;
            if(u==father)rc++;
        }
        low[u]=min(low[u],dfn[v]);
    }
    if(u==father&&rc>=2)cut[u]=1;
}
int main(){
    freopen("Cola.txt","r",stdin);
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        Insert(x,y);Insert(y,x);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])Tarjan(i,i);
    for(int i=1;i<=n;i++)if(cut[i])ans++;
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)if(cut[i])printf("%d ",i);
}

 

posted @ 2017-10-26 21:23  Echo宝贝儿  阅读(191)  评论(0编辑  收藏  举报