UVa 12717 Fiasco

发布时间:2026/10/5 2:12:14

UVa 12717 Fiasco 题目描述Natasha\texttt{Natasha}Natasha在算法课上总是混淆概念。上周Chhaya Murthy\texttt{Chhaya Murthy}Chhaya Murthy教授布置了一个经典问题在加权图中从指定源点出发计算到所有节点的最短路径。而在此之前教授讲授了Prim\texttt{Prim}Prim算法和Dijkstra\texttt{Dijkstra}Dijkstra算法它们看起来相似但功能截然不同。Natasha\texttt{Natasha}Natasha被搞糊涂了她提交了一个与Prim\texttt{Prim}Prim算法非常相似的代码我们称之为Natasha\texttt{Natasha}Natasha算法并且没有充分测试。她的伪代码如下functionShortest(Graph,source):foreach vertex v in Graph:visited[v]:false;dist[v]:infinity;previous[v]:undefined;ans[v]:undefined;endfordist[source]:0;Q:{}// priority queue, pop gives node with smallest dist, tie by smallest idPush(source,dist[source])to QwhileQ isnotempty:Pop node u from Q;visited[u]:true;ifdist[u]infinity:break;foreach neighbor v of u:ifvisited[v]true:continue;alt:edge_cost(u,v);ifaltdist[v]:dist[v]:alt;previous[v]:u;Push(v,dist[v])to Q;endforendwhileforeach node node in Graph:answer:0;u:node;whileprevious[u]is defined:answer:answeredge_cost(u,previous[u]);u:previous[u];endwhileans[node]:answer;returnans;endfunction提交后她的朋友发现了漏洞。为了帮助她Rehan\texttt{Rehan}Rehan要求她不要改变边连接的顶点也不要改变边权重的整体集合她只能重新排列哪些权重分配给哪些边。请帮助她找到一种边权重分配方案使得Natasha\texttt{Natasha}Natasha的算法在重新分配后的图上能够正确输出从源点到所有节点的最短路径。输入格式第一行包含测试用例数TTT1≤T≤151 \le T \le 151≤T≤15。每个测试用例的第一行包含三个整数n,m,sourcen, m, sourcen,m,source2≤n≤25002 \le n \le 25002≤n≤25001≤m≤250001 \le m \le 250001≤m≤250001≤source≤n1 \le source \le n1≤source≤n分别表示节点数、边数和源点编号。接下来mmm行每行三个整数u,v,wu, v, wu,v,w表示节点uuu和vvv之间有一条权重为www的边1≤w≤m1 \le w \le m1≤w≤m。保证图中没有重边或自环图是连通的且所有边的权重互不相同。输出格式对于每个测试用例首先输出一行Case X其中XXX是测试用例编号。然后按输入顺序输出每条边的三个整数u,v,wu, v, wu,v,w每个三元组占一行用空格分隔。如果有多个可行解输出任意一个。样例输入1 7 9 5 2 4 2 1 4 8 7 2 6 3 4 7 5 7 5 7 3 9 6 1 1 6 3 4 5 6 3输出Case 1: 2 4 7 1 4 8 7 2 3 3 4 9 5 7 1 7 3 4 6 1 5 6 3 6 5 6 2题目分析Natasha\texttt{Natasha}Natasha的算法本质上就是Prim\texttt{Prim}Prim算法它维护一个已访问集合每次从优先队列中取出dist最小的节点然后对于未访问的邻居如果边权小于当前记录的dist则更新dist为边权并记录前驱。注意这里的dist并不是从源点到该节点的累计距离而仅仅是连接边的最小权值因此它实际上是在构建一棵最小生成树从源点出发的Prim\texttt{Prim}Prim树。题目要求重新分配边权使用给定的权重集合{1,2,…,m}\{1,2,\dots,m\}{1,2,…,m}使得在这组新权重下Natasha\texttt{Natasha}Natasha算法最终输出的ans沿前驱累加边权恰好等于从源点到每个节点的真实最短路径同样在新权重下。也就是说我们需要构造一组边权排列使得Prim\texttt{Prim}Prim算法选出的边恰好构成一棵最短路径树SPT\texttt{SPT}SPT。解题思路关键观察Prim\texttt{Prim}Prim算法在选择边时总是选择当前已访问集合到未访问集合的最小权边。如果我们能够控制权重的分配使得Prim\texttt{Prim}Prim在扩展时严格按照某种层次顺序进行那么它就能生成一棵特定的树。最短路径树的一个自然候选是从源点出发的BFS\texttt{BFS}BFS树因为它保证了从源点到每个节点的跳数最少。但仅凭跳数少并不足以保证路径总权值最小我们需要进一步设计权值使得BFS\texttt{BFS}BFS树路径的总权值严格小于任何经过非树边的路径。构造方法我们可以利用BFS\texttt{BFS}BFS的顺序来分配权重具体步骤如下从源点sourcesourcesource开始进行BFS\texttt{BFS}BFS遍历整个图。在BFS\texttt{BFS}BFS过程中每当从当前节点uuu第一次访问到一条连接未访问节点vvv的边(u,v)(u,v)(u,v)时就给这条边分配当前最小的未使用权重从111开始递增。这样BFS\texttt{BFS}BFS先发现的边获得较小的权重后发现的边获得较大的权重。为什么这样构造是可行的BFS\texttt{BFS}BFS保证了节点按离源点的跳数深度递增的顺序被访问。因此连接深度ddd和d1d1d1的边会在连接深度d1d1d1和d2d2d2的边之前被分配权重。由于所有权重都是按发现顺序递增的Prim\texttt{Prim}Prim算法在从源点开始扩展时会优先选择这些被早期分配的边。实际上Prim\texttt{Prim}Prim的扩展顺序将完全与BFS\texttt{BFS}BFS的层次顺序一致最终生成的就是这棵BFS\texttt{BFS}BFS树。对于任意一个深度为ddd的节点从源点到它的BFS\texttt{BFS}BFS树路径恰好包含ddd条边且这些边的权重依次为1,2,…,d1,2,\dots,d1,2,…,d因为它们是BFS\texttt{BFS}BFS过程中最先被分配的ddd条边路径总权值为12⋯dd(d1)212\cdotsd \frac{d(d1)}{2}12⋯d2d(d1)​。任何包含非树边的路径其第一条非树边一定是在BFS\texttt{BFS}BFS中较晚被发现即权重较大的边它的权值至少为d1d1d1。而整条路径的总权值必然大于等于这条非树边的权值因此必然大于d(d1)2\frac{d(d1)}{2}2d(d1)​当d≥1d \ge 1d≥1时d(d1)2d\frac{d(d1)}{2} d2d(d1)​d且d1dd1 dd1d但更严格地d(d1)2\frac{d(d1)}{2}2d(d1)​对于d≥2d \ge 2d≥2已经大于d1d1d1对于d1d1d1树路径权值为111而非树边最小为222也满足。所以树路径是严格最短的。因此这种分配方案能够保证BFS\texttt{BFS}BFS树就是新权重下的最短路径树从而Natasha\texttt{Natasha}Natasha算法即Prim\texttt{Prim}Prim会选中这些树边并最终输出正确的最短距离。算法步骤读取n,m,sourcen, m, sourcen,m,source。使用邻接矩阵或邻接表存储图的结构。从sourcesourcesource出发进行BFS\texttt{BFS}BFS初始化一个队列将sourcesourcesource入队。维护一个全局权重计数器w1w 1w1。当队列非空时弹出队首节点uuu遍历所有与uuu相邻的节点vvv如果边(u,v)(u,v)(u,v)尚未被分配权重则将其权重设为www并将www加111同时将vvv入队并标记该边已分配。BFS\texttt{BFS}BFS结束后每条边都被赋予了一个唯一的权重111到mmm。按输入顺序输出每条边的端点及对应的新权重。复杂度分析BFS\texttt{BFS}BFS遍历所有节点和边时间复杂度为O(nm)O(n m)O(nm)。使用邻接矩阵n≤2500n \le 2500n≤2500时每次检查所有邻居需要O(n2)O(n^2)O(n2)但nnn较小可以接受。也可以使用邻接表优化到O(nm)O(n m)O(nm)。空间复杂度O(n2)O(n^2)O(n2)邻接矩阵或O(nm)O(n m)O(nm)邻接表。代码实现// Fiasco// UVa ID: 12717// Verdict: Accepted// Submission Date: 2026-06-24// UVa Run Time: 0.070s//// 版权所有C2026邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;constintMAXN2505;intn,m,source;intg[MAXN][MAXN];// 存储分配后的边权-1 表示无边intorigU[25005],origV[25005];// 保存输入顺序的端点boolvisited[MAXN][MAXN];// 标记边是否已在 BFS 中被分配voidbfs(){queueintq;intweight1;q.push(source);while(!q.empty()){intuq.front();q.pop();for(intv1;vn;v){if(g[u][v]!-1!visited[u][v]){// 边 (u,v) 第一次被发现分配权重g[u][v]g[v][u]weight;visited[u][v]visited[v][u]true;q.push(v);}}}}intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intT;cinT;for(intcs1;csT;cs){cinnmsource;// 初始化邻接矩阵memset(g,-1,sizeof(g));memset(visited,false,sizeof(visited));for(inti0;im;i){intw;cinorigU[i]origV[i]w;// 仅标记存在边权重暂存为 0后续被覆盖g[origU[i]][origV[i]]g[origV[i]][origU[i]]0;}bfs();coutCase cs:\n;for(inti0;im;i)coutorigU[i] origV[i] g[origU[i]][origV[i]]\n;}return0;}总结本题的关键在于将Prim\texttt{Prim}Prim算法的行为引导到构造最短路径树的目标上。通过BFS\texttt{BFS}BFS顺序分配边权我们可以让Prim\texttt{Prim}Prim按照BFS\texttt{BFS}BFS的层次扩展并利用权重递增的特点保证BFS\texttt{BFS}BFS树路径的总权值小于任何包含非树边的路径。这种构造方法巧妙地将图论中的BFS\texttt{BFS}BFS与Prim\texttt{Prim}Prim算法联系起来避免了复杂的贪心证明是解决此类“重排边权使错误算法变正确”问题的经典技巧。核心要点利用BFS\texttt{BFS}BFS天然的分层特性控制边的优先级。权重递增使树路径的权值和与深度挂钩确保最短性。代码实现简洁时间复杂度低适合题目给定的数据范围。
延伸阅读

更多相关文章

2026/10/5 2:07:14

【Java面试题】Java并发

Java 并发面试题汇总Java 并发是 Java 后端面试中的高频考点,尤其是 synchronized、volatile、CAS、AQS、ReentrantLock、线程池、ThreadLocal 等。 本文按照“线程基础 → Java 内存模型 → synchronized → volatile → CAS → AQS → Lock → 线程池 → ThreadLo…

2026/10/5 4:22:19

AI应用架构设计:从Demo到生产,Agent、MCP与并发治理实战

1. 从"能跑通"到"能扛住":AI应用架构设计的真实分水岭很多人第一次搭AI应用,都是从一个脚本开始的:调一次模型接口,拼一段提示词,拿到结果打印出来,收工。这个阶段跑得通,但…

2026/10/5 4:22:19

飞机型号识别数据集:分类与检测双轨并行的工业级基建

简介:本资源是面向计算机视觉算法研究者与深度学习工程师的飞机型号识别专用数据集,聚焦军民飞机目标检测与细粒度分类任务,适用于YOLO、Faster R-CNN等模型训练与评估。数据集采集自俄罗斯机场,涵盖苏霍伊、米格、安东诺夫、伊尔…

2026/10/5 4:22:19

C++类模板从入门到实践:语法、特化、继承与编译期坑点全解析

类模板这东西,我在刚开始写C那会儿一直当成“带类型的宏”来看,后来被几段模板代码反复吊打——编译期能跑出几十屏红字,运行时还能靠特化把逻辑拐得完全不一样。直到有次,我给一个项目写了三份几乎一模一样的容器类,分…

2026/10/5 4:22:19

DeepSeek Harness桌面端实战:工作区、插件与Skill部署指南

1. 桌面端来了,但真正值得聊的是它背后的工作流DeepSeek Harness 出官方桌面端这件事,我第一反应不是"终于不用开浏览器了",而是"这套东西终于可以脱离浏览器沙箱,正经当一个本地开发工具来用了"。如果你之前…

2026/10/5 4:17:19

开源情报(OSINT):从公开信息到结构化画像的完整方法论

前阵子一位做招聘的朋友拿了个网名过来,说面试前想了解一下候选人的公开信息,结果搜出来的都是同名账号,越查越乱。我花了十五分钟,从那条招聘平台动态顺藤摸瓜,找到了技术分享社区的发言、代码托管平台上的个人主页&a…

2026/10/4 0:01:02

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/4 0:01:02

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/4 1:01:05

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑