码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P3388 【模板】割点(割顶)

时间:2017-11-26 11:11:26      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:line   个数   ++   false   als   编号   include   struct   color   

题目背景

割点

题目描述

给出一个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<cstdio>
#include<algorithm>
using namespace std;
inline int read() {
    int x=0,f=1;
    char c=getchar();
    while(c<0||c>9) {
        if(c==-)f=-1;
        c=getchar();
    }
    while(c<=9&&c>=0) {
        x=x*10+c-0;
        c=getchar();
    }
    return x*f;
}
const int maxn = 100007;
int low[maxn],dfn[maxn],head[maxn];
struct node{
    int v,next;
}edge[maxn*2];int num,tn;
bool iscut[maxn];
inline void add_edge(int u,int v) {
    edge[++num].v=v;edge[num].next=head[u];head[u]=num;
}
int ans=0;
void tarjan(int u,int fa) { 
    low[u] = dfn[u] = ++tn;
    int cnt_son = 0;
    for (int i=head[u]; i; i=edge[i].next) {
        int v = edge[i].v;
        if (!dfn[v]) {
            cnt_son++;
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if (low[v]>=dfn[u])
                if(!iscut[u])
                iscut[u]=true,ans++;
        }
        else if(dfn[v]<dfn[u]&&v!=fa) 
            low[u]=min(low[u],dfn[v]);
    }
    if(fa<0&&cnt_son==1) iscut[u]=false,ans--;
}
int main() {
    //while(1){};
    int n=read(),m=read();
    for(int a,b,i=1;i<=m;++i) {
        a=read(),b=read();
        add_edge(a,b);
        add_edge(b,a);
    }
    for(int i=1;i<=n;++i)
        if(!dfn[i])tarjan(i,-1);
    printf("%d\n",ans);
    int qq=0;
    for(int i=1;i<=n;++i) {
        if(iscut[i])printf("%d ",i);
    }
    return 0;
}

 

luogu P3388 【模板】割点(割顶)

标签:line   个数   ++   false   als   编号   include   struct   color   

原文地址:http://www.cnblogs.com/sssy/p/7898202.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!