当前位置:首页 > 技术 > 正文内容

Tarjan算法在图连通分量检测中的应用

访客 技术 2026年6月8日 1

在无向图处理中,推荐使用来源边标识(from)替代父节点(father)进行回溯,以提升代码的通用性。

点双连通分量具有以下性质:若其包含的节点数大于1,则至少存在两个节点。 证明过程: 当仅含单节点时,显然分量大小为1。 当节点数≥2时: 任选两个节点构成子图E。 根据定义,移除图中任一节点不会破坏连通性,故该子图为点双连通。由于点双连通分量是极大子图,其节点数必然不少于2。

边双连通分量的特性是:任意两节点至少存在于一个简单环路中,该性质可用于环路检测。

有向图强连通分量实现:

void strong_connect(int node) {
    dfs_num[node] = low_link[node] = ++counter;
    stack[++stack_top] = node;
    in_stack[node] = true;

    for (int edge = head[node]; edge != -1; edge = next_edge[edge]) {
        int neighbor = edge_end[edge];
        if (!dfs_num[neighbor]) {
            strong_connect(neighbor);
            low_link[node] = min(low_link[node], low_link[neighbor]);
        } 
        else if (in_stack[neighbor]) 
            low_link[node] = min(low_link[node], dfs_num[neighbor]);
    }

    if (dfs_num[node] == low_link[node]) {
        ++component_count;
        int top_node;
        do {
            top_node = stack[stack_top--];
            in_stack[top_node] = false;
            comp_id[top_node] = component_count;
            comp_size[component_count]++;
        } while (top_node != node);
    }
}

无向图点双连通分量实现:

void find_bcc(int current, int in_edge) {
    dfs_num[current] = low_link[current] = ++counter;
    stack[++stack_top] = current;
    int child_count = 0;

    for (int edge = head[current]; edge != -1; edge = next_edge[edge]) {
        int neighbor = edge_end[edge];
        if (!dfs_num[neighbor]) {
            ++child_count;
            find_bcc(neighbor, edge);
            low_link[current] = min(low_link[current], low_link[neighbor]);
            if (low_link[neighbor] >= dfs_num[current]) {
                if (root_node != current || child_count > 1) 
                    is_articulation[current] = true;
                ++bcc_count;
                int top_node;
                do {
                    top_node = stack[stack_top--];
                    bcc_list[bcc_count].push_back(top_node);
                } while (top_node != neighbor);
                bcc_list[bcc_count].push_back(current);
            }
        }
        else if (edge != (in_edge ^ 1)) 
            low_link[current] = min(low_link[current], dfs_num[neighbor]);
    }

    if (current == root_node && !child_count) {
        ++bcc_count;
        --stack_top;
        bcc_list[bcc_count].push_back(current);
    }
}

无向图边双连通分量实现:

void find_ebcc(int vertex, int prev_edge) {
    dfs_num[vertex] = low_link[vertex] = ++counter;
    stack[++stack_top] = vertex;

    for (int edge = head[vertex]; edge != -1; edge = next_edge[edge]) {
        int neighbor = edge_end[edge];
        if (!dfs_num[neighbor]) {
            find_ebcc(neighbor, edge);
            low_link[vertex] = min(low_link[vertex], low_link[neighbor]);
            if (low_link[neighbor] > dfs_num[vertex]) 
                bridge_mark[edge] = bridge_mark[edge ^ 1] = true;
        }
        else if (edge != (prev_edge ^ 1)) 
            low_link[vertex] = min(low_link[vertex], dfs_num[neighbor]);
    }

    if (dfs_num[vertex] == low_link[vertex]) {
        ++ebc_count;
        int top_node;
        do {
            top_node = stack[stack_top--];
            ebc_list[ebc_count].push_back(top_node);
        } while (top_node != vertex);
    }
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。