📜  门|门CS 2008 |第 73 题(1)

📅  最后修改于: 2023-12-03 15:42:22.322000             🧑  作者: Mango

门|门 CS 2008 | 第 73 题

这是一道关于图论的题目,题目描述为:给定一张无向图,求其中的一组基。

什么是一组基?

在图论中,基的定义就是一组互相不连通的边,可以用这些边来覆盖整张图,也就是说每条边都至少有一个端点被基中的某一条边覆盖到了。

如何求一组基?

为了求一组基,我们可以使用 Tarjan 算法。该算法是基于深度优先搜索(DFS)的,其基本思路是先求出整张图的割边,再求出割边之外的基。

在有向图中,Tarjan 算法的时间复杂度为 O(E+V),其中 E 表示边数,V 表示顶点数。

下面是使用 C++ 实现的代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int MAXN = 1e5+5, MAXM = 1e5+5;

int head[MAXN], nxt[MAXM], to[MAXM], dfn[MAXN], low[MAXN], st[MAXN], vis[MAXN];
int cnt, num, top, idx;

void add_edge(int u, int v) {
    to[++cnt] = v;
    nxt[cnt] = head[u];
    head[u] = cnt;
}

void Tarjan(int u, int fa) {
    dfn[u] = low[u] = ++num;
    st[++top] = u;
    vis[u] = true;
    for (int i = head[u]; i; i = nxt[i]) {
        int v = to[i];
        if (v == fa) continue;
        if (!dfn[v]) {
            Tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] >= dfn[u]) {
                idx++;
                while (true) {
                    int x = st[top--];
                    printf("%d ", x);
                    if (x == v) break;
                }
                printf("\n");
            }
        } else if (vis[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    vis[u] = false;
}

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        add_edge(u, v);
        add_edge(v, u);
    }
    Tarjan(1, 0);
    while (top) {
        printf("%d ", st[top--]);
    }
    return 0;
}
运行环境

该算法实现使用了 C++ 语言,可以在任何支持 C++ 的环境中运行。