P3388 割顶 【求割点个数】

 

输入格式

第一行输入两个正整数 n,mn,m。

下面 mm 行每行输入两个正整数 x,yx,y 表示 xx 到 yy 有一条边。

输出格式

第一行输出割点个数。

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

输入输出样例

输入 #1
6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6
输出 #1
1 
5

CODE

#include <bits/stdc++.h>
#define dbg(x) cout << #x << "=" << x << endl

using namespace std;
typedef long long LL;
const int maxn = 1e5 + 7;

int head[maxn], dfn[maxn], low[maxn];
int cnt = 0, tot = 0, tim = 0, top = 1, cl = 0, k;
int vis[maxn];
int color[maxn];
int iscut[maxn];
int tott, n, m;

/*
head[],结构体edge:存边

dfn[],low[]:tarjan中数组

st[]:模拟栈

out[]:出边

sd[]:强连通分量存储

dq[]:统计答案
*/

template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

struct Edge{
    int nxt, to;
}edge[maxn * 2];

inline void BuildGraph(int from, int to)
{
    cnt++;
    edge[cnt].to = to;
    edge[cnt].nxt = head[from];
    head[from] = cnt;
}

stack<int> s;

void tarjan(int u, int fa)
{
    int son = 0;
    s.push(u);
    low[u] = dfn[u] = ++tim;
    for ( int i = head[u]; i; i = edge[i].nxt ) {
        int v = edge[i].to;
        if(!dfn[v]) {
            tarjan(v, fa);
            low[u] = min(low[u], low[v]);
            if(low[v] >= dfn[u] && u != fa) {
                iscut[u] = 1;
            }
            if(== fa) {
                ++son;
            }
        }
        low[u] = min(low[u], dfn[v]);
    }
    if(son >= 2 && u == fa) {
        iscut[1] = 1;
    }
}

void init() {
    cnt = 0;
    cl = 0;
    tim = 0;
    k = 0;
    while(!s.empty()) {
        s.pop();
    }
    
    memset(vis, 0, sizeof(vis));
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(iscut, 0, sizeof(iscut));
    memset(edge, 0, sizeof(edge));
    memset(head, 0, sizeof(head));
}

int main() 
{
    init();
    scanf("%d %d",&n, &m);
    for ( int i = 1; i <= m; ++) {
        int x, y;
        scanf("%d %d",&x, &y);
        BuildGraph(x, y);
        BuildGraph(y, x);
        
    }
    for ( int i = 1; i <= n; ++) {
        if(!dfn[i]) {
            tarjan(i, i);
        }
    }
    for ( int i = 1; i <= n; ++) {
        if(iscut[i]) {
            ++tott;
        }
    }
    printf("%d ",tott);
    for ( int i = 1; i <= n; ++) {
        if(iscut[i]) {
            printf("%d ",i);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/orangeko/p/12433901.html