hihor 学习日记:hiho一下 第五十二周 (割边与割点)

http://hihocoder.com/contest/hiho52/problem/1

题意:

这道题就是求割边与割点,

割边与割点

在这里插入图片描述

思路:

在这里插入图片描述
在这里插入图片描述
大致就是用DFS树来得到low,与dfn比较来判断当前点的子树上的点是否与当前点的父点相连,如果不联,那么去掉当前点,子树与原来的树不再连通,这就是割点。
而割边相同,如果当前点的子树上的点不与当前点以及当前点的父点相连,那么当前点与子树相连的边就是割边

注意:

这道题的割点有可能有相同的,所以最后输出是要去重

AC代码:

#include <bits/stdc++.h>

using namespace std;
#define LL long long
const int Mod = 1e9 + 7;
const int maxn = 1e5 + 5;
const double eps = 0.00000001;
const int INF = 0x3f3f3f3f;

struct Edge{
    int v, next;

    bool friend operator < (Edge a, Edge b) {
        if(a.v == b.v) return a.next < b.next;
        return a.v < b.v;
    }

}edge[maxn << 1], edge2[maxn], edge3[maxn];

int tot1, tot2, tot3, head[maxn];
int vis[maxn], low[maxn], par[maxn], dfn[maxn];

void init() {
    tot1 = tot2 = tot3 = 0;
    memset(head, -1, sizeof(head));
    memset(vis, 0, sizeof(vis));
    memset(par, -1, sizeof(par));
}


void addEdge(int u, int v) {
    edge[tot1].v = v;
    edge[tot1].next = head[u];
    head[u] = tot1 ++;

    edge[tot1].v = u;
    edge[tot1].next = head[v];
    head[v] = tot1 ++;
}


void dfs(int u) {
    static int counter = 0;
    int child = 0;
    vis[u] = 1;
    dfn[u] = low[u] = ++counter;
    for (int i = head[u]; i + 1; i = edge[i].next) {
        int v = edge[i].v;
        if(!vis[v]) {
            child ++;
            par[v] = u;
            dfs(v);
            low[u] = min(low[u], low[v]);
            if(par[u] == -1 && child > 1) edge2[tot2 ++].v = u;
            if(par[u] != -1 && low[v] >= dfn[u]) edge2[tot2 ++].v = u;
            if(low[v] > dfn[u]) {
                edge3[tot3].v = min(u, v);
                edge3[tot3 ++].next = max(u, v);
            }
        }
        else if(v != par[u]){
            low[u] = min(low[u], dfn[v]);
        }
    }
}

int main()
{
    init();
    int N, M;
    cin >> N >> M;
    while(M --) {
        int u, v;
        cin >> u >> v;
        addEdge(u, v);
    }
    dfs(1);
    sort(edge2, edge2 + tot2);
    sort(edge3, edge3 + tot3);
    if(tot2) {
            cout << edge2[0].v;
        for (int i = 1; i < tot2; i ++)
            if(edge2[i].v != edge2[i - 1].v)
                cout << " " << edge2[i].v;
    }else cout << "Null\n";
    cout << endl;
    for (int i = 0; i < tot3; i ++)
        cout << edge3[i].v << " " << edge3[i].next << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/85106334