news 2026/9/2 3:42:21

UVa 796 Critical Links

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 796 Critical Links

题目描述

在计算机网络中,若存在两台服务器AAABBB,使得它们之间的所有网络路径都经过某条链路LLL,则称LLL为关键链路(即桥)。移除一条关键链路会将网络分成两个互不相连的子网。给定一个无向图(可能不连通),要求找出所有关键链路,并按第一个端点升序输出。

输入格式

输入包含多个数据集合,每个集合描述一个网络。第一行为一个整数nnn(可能为000),表示服务器数量。随后nnn行,每行格式为:u (cnt) v1 v2 ...,其中uuu为服务器编号,cntcntcnt为直接连接数,后面cntcntcnt个整数为相邻服务器编号。输入数据正确。服务器编号从000n−1n-1n1。两个数据集合之间无空行分隔,以n=0n=0n=0结束。

输出格式

对于每个数据集合,首先输出一行,格式为k critical links,其中kkk为关键链路数量。然后每行输出一条关键链路,格式为u - vu<vu < vu<v),按uuu升序,若uuu相同按vvv升序排列。每个数据集合输出后跟一个空行。

样例输入

8 0 (1) 1 1 (3) 2 0 3 2 (2) 1 3 3 (3) 1 2 4 4 (1) 3 7 (1) 6 6 (1) 7 5 (0) 0

样例输出

3 critical links 0 - 1 3 - 4 6 - 7 0 critical links

题目分析

求无向图中的所有桥(关键链路),使用Tarjan\texttt{Tarjan}Tarjan算法基于深度优先搜索(DFS\texttt{DFS}DFS)计算每个顶点的dfn\textit{dfn}dfn(发现时间)和low\textit{low}low(能回溯到的最早祖先)。对于边(u,v)(u, v)(u,v),若dfn[u]<low[v]\textit{dfn}[u] < \textit{low}[v]dfn[u]<low[v],则(u,v)(u,v)(u,v)是桥。算法从每个未访问的顶点开始DFS\texttt{DFS}DFS,处理孤立节点和多个连通分量。

解题思路

实现步骤确定如下:

步骤1\texttt{1}1. 读入nnn。若n=0n = 0n=0,则结束。

步骤2\texttt{2}2. 构建邻接表。对每个服务器uuu,读入uuu、括号内的cntcntcnt以及cntcntcnt个邻居vvv,将uuuvvv互相加入邻接表。

步骤3\texttt{3}3. 初始化dfn\textit{dfn}dfnlow\textit{low}lowvisited\textit{visited}visited数组。对于每个未访问顶点uuu,调用DFS(u,parent,depth)\texttt{DFS}(u, parent, depth)DFS(u,parent,depth)

步骤4\texttt{4}4.DFS\texttt{DFS}DFS实现:标记uuu已访问,设置dfn[u]=low[u]=depth\textit{dfn}[u] = \textit{low}[u] = depthdfn[u]=low[u]=depth。遍历邻接顶点vvv

  • vvv是父节点,则跳过。
  • vvv已访问,则更新low[u]=min⁡(low[u],dfn[v])\textit{low}[u] = \min(\textit{low}[u], \textit{dfn}[v])low[u]=min(low[u],dfn[v])
  • vvv未访问,递归调用DFS(v,u,depth+1)\texttt{DFS}(v, u, depth+1)DFS(v,u,depth+1),然后更新low[u]=min⁡(low[u],low[v])\textit{low}[u] = \min(\textit{low}[u], \textit{low}[v])low[u]=min(low[u],low[v])。若dfn[u]<low[v]\textit{dfn}[u] < \textit{low}[v]dfn[u]<low[v],则(u,v)(u, v)(u,v)是桥,加入列表。

步骤5\texttt{5}5. 确保每条桥输出时start<endstart < endstart<end。按startstartstart升序、endendend升序排序并输出。

代码实现

// Critical Links// UVa ID: 796// Verdict: Accepted// Submission Date: 2016-11-30// UVa Run Time: 0.000s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constintMAXV=2010;structedge{intstart,end;booloperator<(constedge&x)const{if(start!=x.start)returnstart<x.start;elsereturnend<x.end;}};vector<int>g[MAXV];vector<edge>bridge;intdfn[MAXV],low[MAXV],visited[MAXV];voiddfs(intu,intparent,intdepth){visited[u]=1;dfn[u]=low[u]=depth;for(autov:g[u]){if(v!=parent&&visited[v]==1)low[u]=min(low[u],dfn[v]);if(!visited[v]){dfs(v,u,depth+1);low[u]=min(low[u],low[v]);if(dfn[u]<low[v])bridge.push_back((edge){u,v});}}visited[u]=2;}intmain(intargc,char*argv[]){intservers;while(cin>>servers){for(inti=0;i<servers;i++)g[i].clear();string s;for(inti=1,u,v,c;i<=servers;i++){cin>>u>>s;c=stoi(s.substr(1,s.length()-2));for(intj=1;j<=c;j++){cin>>v;g[u].push_back(v);g[v].push_back(u);}}bridge.clear();memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(visited,0,sizeof(visited));for(intu=0;u<servers;u++)if(!visited[u])dfs(u,-1,1);for(inti=0;i<bridge.size();i++)if(bridge[i].start>bridge[i].end)swap(bridge[i].start,bridge[i].end);cout<<bridge.size()<<" critical links\n";sort(bridge.begin(),bridge.end());for(inti=0;i<bridge.size();i++)cout<<bridge[i].start<<" - "<<bridge[i].end<<'\n';cout<<'\n';}return0;}

总结

本题通过Tarjan\texttt{Tarjan}Tarjan算法在O(V+E)O(V+E)O(V+E)时间内找出无向图的所有桥。关键在于正确维护low\textit{low}low值,并利用dfn[u]<low[v]\textit{dfn}[u] < \textit{low}[v]dfn[u]<low[v]判断桥。输入格式中括号内的连接数需解析,使用字符串处理提取数字。输出要求按startstartstart升序,并保证start<endstart < endstart<end。该算法适用于顶点数多达200020002000的规模,效率较高。理解DFS\texttt{DFS}DFS树和回边的关系是解决此类问题的核心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 3:41:06

用Spewer把Codex/Claude任务委托给便宜模型节省成本

Spewer 这类工具&#xff0c;核心就是把你给 Codex CLI 和 Claude Code 下的任务&#xff0c;转发到更便宜的模型上去跑。听起来像绕路&#xff0c;实际解决的是很现实的问题&#xff1a;Codex 和 Claude Code 的 agent 能力很强&#xff0c;但按 token 计费&#xff0c;越强的…

作者头像 李华
网站建设 2026/9/2 3:40:34

Python并发编程实战:多线程、多进程与线程池进程池应用指南

这次我们来看一套完整的 Python 并发编程教程。对于任何想要提升程序性能、处理 I/O 密集型任务或构建高响应应用的开发者来说&#xff0c;并发编程都是绕不开的核心技能。这套教程从零基础出发&#xff0c;覆盖了多线程、多进程、线程同步、进程通信以及 ThreadLocal 等关键概…

作者头像 李华
网站建设 2026/9/2 3:40:04

FPGA实时人脸检测实战:基于肤色检测的流水线设计

简介&#xff1a;面向咸鱼FPGA平台的人脸检测学习需求&#xff0c;代码实现了从肤色模型建立到二值图像输出的完整流程。设计采用YCbCr颜色空间进行肤色识别&#xff0c;通过人工阈值法将肤色区域与非肤色区域分离&#xff0c;最终生成二值图像&#xff0c;适用于需要入门FPGA图…

作者头像 李华
网站建设 2026/9/2 3:40:00

mklittlefs交叉编译实战:从文件名解读到LittleFS镜像制作

简介&#xff1a;面向Windows 64位环境下的ESP32开发者&#xff0c;有一款基于MinGW-w64交叉编译工具链的mklittlefs命令行工具&#xff0c;用于创建和管理LittleFS文件系统镜像。该工具主要解决在电脑端为ESP32生成文件系统镜像的问题&#xff0c;特别适合需要将网页、配置或静…

作者头像 李华
网站建设 2026/9/2 3:39:46

Windows下用mklittlefs生成littlefs镜像:从工具链到避坑实践

简介&#xff1a;面向ESP32开发者的Windows专用工具包&#xff0c;内含mklittlefs可执行程序&#xff0c;作用是在个人电脑上创建、格式化并打包LittleFS文件系统镜像&#xff0c;解决为微控制器设备预置文件系统时缺少便捷工具的问题。LittleFS本身是专为资源受限硬件设计的轻…

作者头像 李华
网站建设 2026/9/2 3:38:45

从零开始学Python:写给初学者的进阶路线图

拿到一本Python书&#xff0c;大多数人从第一章开始读&#xff0c;然后在某个深夜放弃。这不是意志力问题&#xff0c;而是路径错了。从零开始学Python&#xff0c;最不需要的就是“系统的阅读”&#xff0c;最需要的是“粗糙的练习”。 你的第一行代码应该是print(“hello wor…

作者头像 李华