• 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 图不一定联通!!!

    分析

    tarjan求割点

    code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdlib>
     6 
     7 using namespace std;
     8 
     9 const int N = 100100;
    10 struct Edge{
    11     int to,nxt;
    12 }e[N<<1];
    13 int head[N],dfn[N],low[N];
    14 bool iscut[N];
    15 int tn,tot;
    16 
    17 inline char nc() {
    18     static char buf[100000],*p1 = buf,*p2 = buf;
    19     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
    20 }
    21 inline int read() {
    22     int x = 0,f = 1;char ch = nc();
    23     for (; ch<'0'||ch>'9'; ch = nc()) 
    24         if (ch=='-') f = -1;
    25     for (; ch>='0'&&ch<='9'; ch = nc()) 
    26         x = x*10+ch-'0';
    27     return x * f;
    28 }
    29 
    30 void add_edge(int u,int v) {
    31     e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot;
    32 }
    33 
    34 void tarjan(int u,int fa) {
    35     low[u] = dfn[u] = ++tn;
    36     int cnt_son = 0;
    37     for (int i=head[u]; i; i=e[i].nxt) {
    38         int v = e[i].to;
    39         if (!dfn[v]) {
    40             cnt_son++;
    41             tarjan(v,u);
    42             low[u] = min(low[u],low[v]);
    43             if (low[v] >= dfn[u]) 
    44                 iscut[u] = true;
    45         }
    46         else if (dfn[v] < dfn[u] && v != fa) 
    47             low[u] = min(low[u],dfn[v]);
    48     }
    49     if (fa<0 && cnt_son==1) iscut[u] = false;
    50 }
    51 int main() {
    52     int n = read(),m = read();
    53     for (int u,v,i=1; i<=m; ++i) {
    54         u = read(),v = read();
    55         add_edge(u,v),add_edge(v,u);
    56     }
    57     for (int i=1; i<=n; ++i) 
    58         if (!dfn[i]) tarjan(i,-1);
    59 
    60     int ans = 0;
    61     for (int i=1; i<=n; ++i) 
    62         if (iscut[i]) ans++;
    63     printf("%d
    ",ans);
    64     for (int i=1; i<=n; ++i) 
    65         if (iscut[i]) printf("%d ",i);
    66     return 0;
    67 }
  • 相关阅读:
    (Java实现) 洛谷 P1106 删数问题
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1106 删数问题
    目测ZIP的压缩率
  • 原文地址:https://www.cnblogs.com/mjtcn/p/7895868.html
Copyright © 2020-2023  润新知