P3388 【模板】割點

 

題目背景

割點node

題目描述

給出一個n個點,m條邊的無向圖,求圖的割點。c++

輸入輸出格式

輸入格式:spa

 

第一行輸入n,mblog

下面m行每行輸入x,y表示x到y有一條邊it

 

輸出格式:io

 

第一行輸出割點個數class

第二行按照節點編號從小到大輸出節點,用空格隔開im

 

輸入輸出樣例

輸入樣例#1:  複製
6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6
輸出樣例#1:  複製
1 
5

說明

n,m均爲100000di

tarjan圖不必定聯通!!!vi

點的編號均大於0小於等於n

 

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int MAXN=1e5+10;
struct node{
    int v;
    int Next;
}edge[MAXN<<1 ];
int head[MAXN], cnt,low[MAXN],dfn[MAXN],Time;
bool vis[MAXN];
void add(int u,int v)
{
    edge[++cnt].v=v;
    edge[cnt].Next=head[u];
    head[u]=cnt;
}

void tarjan(int u,int fa)
{
    dfn[u]=low[u]=++Time;
    int child=0;
    for (int i = head[u]; i !=-1 ; i=edge[i].Next) {

        int v=edge[i].v;

        if(!dfn[v]) {  //沒有被訪問過。

            tarjan(v,fa);
            low[u]=min(low[u],low[v]);

            if(low[v]>=dfn[u]&&u!=fa)//一個點能鏈接到最遠的祖先節點仍大於或者等於他的父親節點,那麼他的父親節點必定是割點
                vis[u]=1;

            if(u==fa) child++;
        }
        low[u]=min(low[u],dfn[v]);//求割點時只能是dfn[v],強連通份量能夠是dfn[v]||low[v]
    }
    if(child>=2&&u==fa)
        vis[u]=1;


}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    memset(head,-1, sizeof(head));
    int u,v;
    for (int i = 0; i <m ; ++i) {
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }
    for (int i = 1; i <=n ; ++i) {
        if(!dfn[i]) tarjan(i,i);
    }
    int sum=0;
    for (int i = 1; i <=n ; ++i) {
        if(vis[i]) sum++;
    }
    printf("%d\n",sum);
    for (int i = 1; i <=n ; ++i) {
        if(vis[i]) printf("%d ",i);
    }
    return 0;
}
相關文章
相關標籤/搜索