当前位置: 首页 > news >正文

UVa 610 Street Directions

题目描述

根据汽车碰撞监测机构(ACM\texttt{ACM}ACM)的统计,大多数致命交通事故发生在双向街道上。为了减少交通事故造成的伤亡,市长希望将尽可能多的街道改为单行街道。你需要完成这一转换,使得从每个交叉路口出发,驾驶员都能沿着某条路线到达所有其他交叉路口。

给定城市中所有街道的列表(均为双向街道)。每条街道连接两个交叉路口,且不经过其他交叉路口。每个交叉路口最多与四条街道相连,任意一对交叉路口之间最多有一条街道。可能存在只有一条街道连接的交叉路口。你可以假设当所有街道都是双向时,从任意一个目的地都能到达其他任意目的地。

输入格式

输入包含多个测试用例。每个测试用例的第一行包含两个整数nnnmmm,分别表示交叉路口的数量(2≤n≤10002 \le n \le 10002n1000)和街道的数量。接下来的mmm行每行包含两个整数,表示一条街道所连接的两个交叉路口编号(编号从111nnn)。每条街道只列出一次,如果出现i j,则不会出现j i。输入以n = m = 0结束。

输出格式

对于每个测试用例,首先输出该用例的编号(从111开始),然后输出一个空行。接下来,每行输出一个方向分配,格式为i j,表示街道方向从交叉路口iiijjj。对于无法转换为单行的街道,需要输出两行,分别为i jj i$。街道列表可以按任意顺序输出。每个测试用例的输出以单独一行#` 结束。

样例

输入

7 10 1 2 1 3 2 4 3 4 4 5 4 6 5 7 6 7 2 5 3 6 7 9 1 2 1 3 1 4 2 4 3 4 4 5 5 6 5 7 7 6 0 0

输出

1 1 2 2 4 3 1 3 6 4 3 5 2 5 4 6 4 6 7 7 5 # 2 1 2 2 4 3 1 4 1 4 3 4 5 5 4 5 6 6 7 7 5 #

题目分析

本题的核心是无向连通图的方向化问题。给定一个无向连通图,要求将尽可能多的边定向为有向边,同时保证最终的有向图仍然是强连通的(即从任意节点可以到达任意其他节点)。显然,如果一条边是桥(割边),即删除该边会导致图不连通,那么这条边必须保留双向,否则两个连通分量之间将无法相互到达。对于非桥边,由于其两端存在另一条路径,我们可以将其定向为单向,而不会破坏强连通性。因此,问题转化为:识别图中的所有桥,将非桥边定向为任意方向,桥边保留双向。

我们可以采用一种基于“尝试删除”的方法,避免显式计算桥。它遍历每条边的两个方向,尝试删除该方向(即临时从邻接表中移除该有向边),然后检查起点能否到达终点。若删除后仍然连通,说明该方向并非必须保留,可以将其删除(即只保留相反方向),从而实现单向;若删除后不连通,则必须保留该方向,最终表现为双向。这种方法在实现上较为简洁,且能直接输出满足要求的定向方案。

解题思路

  1. 存储图:使用邻接表way存储无向图,每个节点i的邻接表中包含所有与其直接相连的节点编号。由于每条边是无向的,邻接表中会同时存储i->jj->i两条有向记录。

  2. 定向过程:遍历每个节点i的邻接表,对于每条有向记录i->j(其中save = way[i][j]),检查该有向边是否已经被处理过(通过集合broken记录已处理的有向边对)。如果未处理,则尝试将其删除:

    • way[i][j]临时设为-1(表示该方向不存在)。
    • 使用深度优先搜索(DFS\texttt{DFS}DFS)检查从i出发能否到达save。若可以到达,说明删除该方向后图仍然连通,因此该方向不是必须的,可以永久删除(保持-1),并标记i->save为已处理。
    • 若不能到达,说明该方向必须保留,则恢复way[i][j] = save,并标记该方向已处理,以防止后续再次尝试删除。
  3. 输出:完成所有方向的尝试后,再次遍历邻接表,输出所有仍为正数(未被删除)的有向边。若某条无向边两个方向都被保留,则会输出两行,分别表示两个方向;若只保留一个方向,则只输出一行。

  4. 正确性保证:由于非桥边至少有一个方向可以被删除,桥边的两个方向都不能删除,最终结果满足强连通性。算法通过逐一尝试删除每个方向,保证了定向方案的有效性。

复杂度分析

  • 对于每条有向边(共2m2m2m条),尝试删除并执行一次DFS\texttt{DFS}DFS,每次DFS\texttt{DFS}DFS的时间复杂度为O(n+m)O(n + m)O(n+m)
  • 总时间复杂度为O(m⋅(n+m))O(m \cdot (n + m))O(m(n+m)),在最坏情况下m=O(n2)m = O(n^2)m=O(n2),可能较大,但由于n≤1000n \le 1000n1000且实际数据较稀疏,该算法在给定时限内可运行通过(参考代码运行时间为0.7500.7500.750秒)。
  • 空间复杂度为O(n+m)O(n + m)O(n+m)

代码实现

// Street Directions// UVa ID: 610// Verdict: Accepted// Submission Date: 2016-08-31// UVa Run Time: 0.750s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;vector<vector<int>>way;intvisited[1001];voiddfs(inti){for(autoe:way[i])if(e>0&&!visited[e]){visited[e]=1;dfs(e);}}boolconnected(inti,intj){memset(visited,0,sizeof(visited));dfs(i);returnvisited[j];}intmain(){cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);intn,m,from,to,cases=0;while(cin>>n>>m,n){cout<<++cases<<"\n\n";way.assign(n+1,vector<int>());for(inti=1;i<=m;i++){cin>>from>>to;way[from].push_back(to);way[to].push_back(from);}set<int>broken;for(inti=1;i<=n;i++)for(intj=0;j<way[i].size();j++){intsave=way[i][j];if(broken.find(i*10000+save)==broken.end()&&broken.find(save*10000+i)==broken.end()){way[i][j]=-1;if(!connected(i,save))way[i][j]=save;elsebroken.insert(i*10000+save);}}for(inti=1;i<=n;i++)for(intj=0;j<way[i].size();j++)if(way[i][j]>0)cout<<i<<' '<<way[i][j]<<'\n';cout<<"#\n";}return0;}

总结

本题通过模拟删除有向边并检查连通性的方法,巧妙地实现了无向图的方向化,使得最终有向图保持强连通且单向边数量最大化。该方法避免了显式求桥的复杂算法,实现简单直观,适用于节点数和边数适中的场景。关键点在于理解桥与非桥边在方向化过程中的不同处理方式,以及利用DFS\texttt{DFS}DFS进行连通性检验。此解法也展示了在图上进行“试探-验证”策略的实用性。

http://www.jsqmd.com/news/1088117/

相关文章:

  • 054、CoTAttention 上下文注意力在 YOLOv11 中的实现:捕获上下文信息的卷积式注意力
  • 数据库架构演进:分库分表到 TiDB 新一代分布式存储的选型决策
  • 什么是 C++ 智能指针
  • YOLO深度学习融合DeepSeekQwen双大模型西瓜病虫害智能诊断Web平台|智慧农业田间植保视觉检测全栈实战项目
  • 龙口值得长期合作防水公司
  • WE Learn网课助手:如何用开源工具告别熬夜刷课烦恼
  • AIGlasses项目.env文件安全配置全解析:从密钥管理到注入防护
  • 缓存完全指南:从 CPU 缓存到 .NET Core WebAPI 生产级“万金油“方案
  • 058、SimAM 能量函数注意力在 C3k2 块内部的插入:通过能量最小化识别重要神经元
  • 【软工方法论50】容量规划与评估
  • Claude Code使用:CC配置第三方模型后,内置工具到底用的谁的?
  • APC模型:从理论到实践,如何拆解社会变迁的密码
  • 问卷考试系统全链路测试实战:从接口自动化到高并发性能调优
  • 瑞萨RA8T2 RTC模块实战:从闹钟配置到低功耗唤醒全解析
  • Snap.Hutao:你的原神游戏效率提升器,告别繁琐管理
  • 无车之境:归零后的新纪元
  • Rogowski 线圈 0.01S 级高精度电流检测完整软硬件实现详解
  • 【Agentic RL / 强化学习框架】Miles 项目技术分析---(1)--- 总体
  • 红帆iOffice.net SQL注入漏洞深度剖析与防护实践
  • 5个专业技巧:如何用FLIP Fluids插件解决Blender流体模拟的核心难题 [特殊字符]
  • 如何快速解决微信QQ语音播放难题:silk-v3-decoder音频转换终极指南
  • 间歇性网站故障排查:「有时慢有时好」的科学点检方法
  • 包管理器安全风险深度解析:从供应链污染到企业级防御实践
  • 智慧职教全自动学习脚本:3分钟告别手动刷课烦恼
  • ReBalance:无需重训练即可实现推理精度+10%、长度-35%的动态思考调控
  • SQL注入进阶:报错、堆叠、头部与Cookie注入实战解析
  • API安全配置实战:从密钥管理到纵深防御体系构建
  • 嵌入式定时器实战:RL78 MCU脉冲测量与PWM输出API详解
  • 第8章:Agent 模式入门——让 AI 学会调用工具
  • 终极字体资源库:15款专业字体一键获取完整指南