Floyd算法实战:C语言解“哈利·波特的考试”图论问题
1. 题目解析与核心需求拆解“哈利·波特的考试”这道题是很多C语言学习者和算法初学者在练习数据结构尤其是图论时会遇到的一道经典题目。我第一次看到这个标题时也以为会有什么魔法咒语或者复杂的剧情逻辑但实际上它考察的是一个非常纯粹的图论算法问题——多源最短路径。题目背景通常是这样霍格沃茨有N门魔法课每门课可以看作一个顶点课程之间的转换难度或者说是“魔法值”构成了带权有向图的边。哈利·波特需要找到一门“最难”的课这里的“最难”不是指课程本身内容而是指从这门课出发到其他所有课程中最难到达的那门课所需要的“魔法值”最大。听起来有点绕别急我们换个说法。这本质上是一个单源最短路问题的集合。对于每一门课即每一个顶点我们都需要计算它到其他所有顶点的最短距离。然后对于这门课我们找出这些最短距离中的最大值即从这门课出发到最难到达的课程的距离。最后我们比较所有课程的这些“最难到达距离”找出其中最小的那个以及对应的课程。如果存在多门课满足条件则输出编号最小的。如果存在某门课无法到达其他所有课即图不连通则输出0。所以核心算法需求非常明确建立图模型将课程和转换难度建模为带权有向图。计算任意两点间最短路径这是算法的核心。由于需要计算所有顶点对之间的最短路径使用 Floyd-Warshall 算法是最直接的选择。它的时间复杂度是 O(N³)对于题目常见的 N ≤ 100 的数据范围是完全可行的。后处理与结果判定对每个顶点 i找出dist[i][1...N]中的最大值maxDist[i]即从i出发到其他点的最远距离。然后在所有maxDist[i]中找出最小值minOfMaxDist。如果某个maxDist[i]为无穷大表示有不可达的顶点则整体结果无效。理解了需求我们再来看看实现中的几个关键点这也是新手最容易栽跟头的地方。2. 图的数据结构与Floyd算法实现精讲2.1 邻接矩阵的初始化无穷大与自环在C语言中我们通常用一个二维数组dist[N1][N1]来表示邻接矩阵并直接作为Floyd算法的距离矩阵。初始化是第一步也是决定算法正确性的基石。#define MAX_V 105 // 假设最大顶点数略大于题目范围 #define INF 0x3f3f3f3f // 一个常用的“无穷大”值 int dist[MAX_V][MAX_V]; int N, M; // N顶点数M边数 void initGraph() { // 1. 自己到自己的距离为0 for (int i 1; i N; i) { for (int j 1; j N; j) { if (i j) { dist[i][j] 0; } else { dist[i][j] INF; // 初始化为无穷大表示不可达 } } } // 2. 读入边信息 // 假设输入格式为顶点a, 顶点b, 权值w for (int k 0; k M; k) { int a, b, w; scanf(%d %d %d, a, b, w); dist[a][b] w; // 有向图 // 如果题目是无向图则需要加上 dist[b][a] w; } }这里有几个极易出错的细节INF的选择为什么是0x3f3f3f3f这个值约等于10^9在int范围内且两个这样的值相加不会溢出0x3f3f3f3f * 2 0x7fffffff。如果你用INT_MAX或0x7fffffff在松弛操作dist[i][k] dist[k][j]时一旦dist[i][k]为最大值相加就会导致整数溢出变成负数从而影响算法结果。0x3f3f3f3f是一个安全且方便 memset 初始化的值memset(dist, 0x3f, sizeof(dist))会将所有字节设为0x3f对于int数组每个int就变成了0x3f3f3f3f。自环距离为0dist[i][i] 0必须显式设置。这是Floyd算法正确工作的前提表示从自己到自己的最短距离是0。虽然逻辑上显而易见但忘记初始化会导致后续判断出错。重边处理题目通常会说“题目保证输入数据是有效的”但有些题目可能存在重边即同一对顶点有多条边。这时需要取最小值dist[a][b] min(dist[a][b], w)。养成这个习惯能避免很多隐蔽的bug。2.2 Floyd-Warshall算法的三重循环顺序与逻辑Floyd算法的核心代码非常简短但内涵深刻。void floyd() { for (int k 1; k N; k) { // 中间点 for (int i 1; i N; i) { for (int j 1; j N; j) { // 关键防止INF相加溢出必须先判断 if (dist[i][k] INF dist[k][j] INF) { if (dist[i][j] dist[i][k] dist[k][j]) { dist[i][j] dist[i][k] dist[k][j]; } } } } } }为什么k循环必须放在最外层这是理解Floyd算法的关键。算法的思想是动态规划dist[k][i][j]表示只允许使用前k个顶点作为中间点从i到j的最短路径长度。当k从1遍历到N时我们逐渐放宽“可使用的中间点”的范围最终得到任意两点间的最短路径。将状态压缩到二维数组后就要求k这层循环必须在外层以保证在计算dist[i][j]时dist[i][k]和dist[k][j]已经是考虑了前k-1个中间点的最优解。如果顺序错了结果就不正确。关于INF的判断这是实现中的另一个关键点。如果dist[i][k]或dist[k][j]是INF那么它们的和是无意义的直接比较可能会因为INF被定义为一个具体的大数而产生错误更新。因此必须先判断两者都不是INF再进行松弛操作。有些简单的实现省略了这个判断在INF选择得当且题目数据保证不会出现INF某值的情况下可能也能通过但加上判断是更严谨、更安全的做法。3. 结果计算与边界条件处理Floyd算法跑完后dist矩阵就存储了所有点对之间的最短距离。接下来就需要根据题目要求找出哈利·波特应该参加的那门考试课程。int findExamCourse() { int minOfMaxDist INF; // 记录所有“最难距离”中的最小值 int examCourse 0; // 对应的课程编号 for (int i 1; i N; i) { int maxDistForI 0; // 从课程i出发到其他课程的最远最短距离 // 遍历所有其他课程j for (int j 1; j N; j) { if (dist[i][j] maxDistForI) { maxDistForI dist[i][j]; } } // 关键判断如果从i出发存在不可达的课程则maxDistForI会是INF if (maxDistForI INF) { // 这门课无法作为起点因为它不能到达所有其他课 // 根据题目要求一旦出现这种情况整个结果就是0 // 但我们需要遍历完所有课程确认吗其实找到第一个就可以返回0了。 // 更严谨的做法记录下这个情况但继续循环因为题目要求输出编号最小的可行课程。 // 实际上如果有一门课不可达那么“所有最难距离中的最小值”这个集合就不完整最终结果应为0。 // 我们可以在循环外用一个标志位记录。 } // 如果这门课可以到达所有其他课则用它的最难距离去更新全局最小值 if (maxDistForI minOfMaxDist) { minOfMaxDist maxDistForI; examCourse i; } } // 后处理检查是否所有课程都能作为起点即图是强连通的不题目要求是每个顶点都能到其他所有顶点这是“竞赛图”的连通性 // 实际上题目要求的是如果存在至少一门课从它出发可以到达其他所有课那么就在这些课里找“最难距离”最小的。 // 如果不存在这样的课即对于每个顶点i都存在另一个顶点j使得dist[i][j]INF则输出0。 // 更准确的判断逻辑 int canFind 0; int globalMinMax INF; int ansId 0; for (int i 1; i N; i) { int maxDist -1; int isConnected 1; // 假设i能到所有点 for (int j 1; j N; j) { if (dist[i][j] maxDist) { maxDist dist[i][j]; } if (dist[i][j] INF) { isConnected 0; // i无法到达j break; // 已经确定i无效内层循环可以提前结束 } } if (isConnected) { // i可以到达所有顶点 canFind 1; if (maxDist globalMinMax) { globalMinMax maxDist; ansId i; } } } if (canFind) { // 输出 ansId 和 globalMinMax printf(%d %d\n, ansId, globalMinMax); } else { printf(0\n); } return 0; }这部分代码的逻辑比看起来要复杂主要体现在连通性判断上。题目真正的意思是在那些能够到达其他所有顶点的顶点中找一个“最难距离”即到其他点的最短距离的最大值最小的。如果不存在这样的顶点即对于图中每一个顶点至少存在一个它无法到达的顶点则输出0。常见的错误理解认为需要整个图是强连通图任意两点互相可达。其实不需要只需要存在一个顶点它能到达其他所有点即可。这个顶点就像是一个“源点”。在计算maxDistForI时如果遇到INF不能简单地将其当作一个巨大值参与比较。因为INF意味着不可达这门课本身就应该被排除在候选之外。所以必须在计算maxDistForI的过程中一旦发现INF就标记该顶点无效。输出要求如果找到输出编号最小的那个课程及其对应的“最难距离”。所以我们在更新globalMinMax时判断条件是maxDist globalMinMax而不是。这样当距离相等时不会更新ansId从而保证了编号小的优先因为我们是按编号从小到大遍历的。4. 完整代码实现与测试用例分析将以上所有部分组合起来并加上输入输出就得到了完整的解决方案。下面是一个整合后的代码框架并附上详细的注释。#include stdio.h #include string.h #define MAX_V 105 #define INF 0x3f3f3f3f int dist[MAX_V][MAX_V]; int N, M; void initGraph() { // 使用memset初始化所有距离为INF非常高效 memset(dist, 0x3f, sizeof(dist)); for (int i 1; i N; i) { dist[i][i] 0; // 自环为0 } for (int i 0; i M; i) { int a, b, w; scanf(%d %d %d, a, b, w); // 处理可能的重复边取最小值 if (w dist[a][b]) { dist[a][b] w; } } } void floyd() { for (int k 1; k N; k) { for (int i 1; i N; i) { // 一个小优化如果i到k不可达则跳过对j的循环 if (dist[i][k] INF) continue; for (int j 1; j N; j) { // 防止INF相加溢出 if (dist[k][j] INF) continue; int newDist dist[i][k] dist[k][j]; if (dist[i][j] newDist) { dist[i][j] newDist; } } } } } int main() { scanf(%d %d, N, M); initGraph(); floyd(); int candidateId 0; int globalMinMaxDist INF; // 遍历每一门课寻找符合条件的“源点” for (int i 1; i N; i) { int maxDist -1; int isValid 1; // 标记顶点i是否可达所有其他顶点 for (int j 1; j N; j) { if (dist[i][j] maxDist) { maxDist dist[i][j]; } // 如果发现不可达的点则顶点i无效 if (dist[i][j] INF) { isValid 0; break; // 提前结束内层循环 } } // 如果顶点i有效且它的“最难距离”是目前最小的 if (isValid maxDist globalMinMaxDist) { globalMinMaxDist maxDist; candidateId i; } } if (candidateId 0) { // 没有找到任何一个顶点能到达所有其他顶点 printf(0\n); } else { printf(%d %d\n, candidateId, globalMinMaxDist); } return 0; }现在我们来设计几个测试用例验证代码的正确性。测试用例1基础连通案例输入 6 11 3 4 70 1 2 1 5 4 50 2 6 50 5 6 60 1 3 70 4 6 60 3 6 80 5 1 100 2 4 60 5 2 80这是一个经典测试图需要手动计算或信任已知结果预期输出应该是2 60。顶点2到其他点的最短距离最大值是60到顶点4在所有顶点中这个值最小。测试用例2存在不可达顶点输入 3 2 1 2 10 2 3 20顶点1无法到达顶点3dist[1][3] INF。顶点2可以到达1和3。顶点3无法到达1。因此只有顶点2是有效的“源点”。它的maxDist是max(20, 0) 20到顶点3的距离是20到自己的距离是0。输出应为2 20。测试用例3全不连通输入 4 0没有边。对于任何一个顶点i到其他任意j (j!i)的距离都是INF。因此不存在有效的“源点”。输出应为0。测试用例4多个候选取编号最小输入 4 3 1 2 5 1 3 5 1 4 5只有顶点1可以到达2、3、4。顶点2、3、4都无法到达其他非自身的顶点。所以唯一有效的是顶点1它的maxDist是5。输出1 5。如果图是对称的无向边那么每个顶点都能到达其他点且maxDist都相等此时应输出编号最小的顶点1。通过这些测试可以全面检查算法的连通性判断、最值比较和边界处理是否正确。在你自己编写时务必用这些案例测试一下这是调试和确保代码鲁棒性的好习惯。

相关新闻

Flutter+OpenHarmony开发逆向思维训练App实践

Flutter+OpenHarmony开发逆向思维训练App实践

1. 逆向思维训练App的跨界开发背景在移动应用开发领域,Flutter因其跨平台特性已成为主流选择之一,而OpenHarmony作为新兴操作系统也正吸引着越来越多开发者的目光。这次我们要开发的是一款结合逆向思维训练和学习日历功能的复合型应用,技术栈…

2026/8/13 23:49:16 阅读更多 →
windows 驱动实例分析系列: wintun驱动分析-example篇(上)

windows 驱动实例分析系列: wintun驱动分析-example篇(上)

Wintun Example 示例程序深度解析 这部分作为演示如何使用wintun驱动进行二次开发的例子,分为两部分。 一、模块概述 example 文件夹是 Wintun 项目提供的一个完整的、可直接运行的示例程序,用于演示如何使用 wintun.dll 的 API 来创建虚拟网络适配器、配…

2026/8/13 23:49:16 阅读更多 →
北邻京网站茵建设:小站深耕长尾流量的逆袭之路

北邻京网站茵建设:小站深耕长尾流量的逆袭之路

在这个流量为王、大V横行的互联网时代,很多人一听到“建站”这两个字,脑子里蹦出来的全是高大上的电商平台、炫酷的3A级门户或者动辄百万预算的定制化开发。大家总觉得,只有那些拥有庞大服务器集群、顶尖UI设计团队和海量资金支撑的项目,才配叫“做网站”。然而,现实往往是…

2026/8/13 23:49:16 阅读更多 →

最新新闻

斩矛剑圣从入门到毕业:一套能看懂、能照抄的物理输出养成路线

斩矛剑圣从入门到毕业:一套能看懂、能照抄的物理输出养成路线

斩矛剑圣从入门到毕业:一套能看懂、能照抄的物理输出养成路线 【免费下载链接】Wotr-BD-LR 正义之怒Wotr主角BD搜集 项目地址: https://gitcode.com/GitHub_Trending/wo/Wotr-BD-LR 同样是剑圣,为什么别人的斩矛一回合三杀、刀刀重击,…

2026/8/14 6:09:01 阅读更多 →
Gitee SSH密钥指纹生成失败:原理、排查与完整解决方案

Gitee SSH密钥指纹生成失败:原理、排查与完整解决方案

1. 问题场景:当Gitee SSH密钥配置卡在“指纹生成失败” 最近在帮团队新成员配置开发环境时,又遇到了一个经典但令人头疼的问题:在Gitee上配置SSH密钥,系统一直提示“指纹生成失败”。这哥们儿对着命令行窗口,反复执行…

2026/8/14 6:09:01 阅读更多 →
SPZ与PLY文件对比测试:10倍压缩比背后的视觉质量评估

SPZ与PLY文件对比测试:10倍压缩比背后的视觉质量评估

SPZ与PLY文件对比测试:10倍压缩比背后的视觉质量评估 【免费下载链接】spz File format for 3D Gaussian splats. About 10x smaller than the PLY equivalent with virtually no perceptible loss in visual quality. Offered as open source by Niantic Labs. Mor…

2026/8/14 6:09:01 阅读更多 →
差旅管理服务性价比解读:2026主流服务商资质与服务梳理

差旅管理服务性价比解读:2026主流服务商资质与服务梳理

差旅管理服务采购的几个常见疑问当前不少企业在引入差旅管理服务前,普遍围绕「差旅管理服务贵不贵」产生系列共性疑问,核心集中在五大方面。首先是收费构成问题,不少企业不清楚差旅管理服务除了基础的资源采购相关费用外,是否包含…

2026/8/14 6:09:01 阅读更多 →
大麦自动抢票开源项目实战:Selenium+Appium 双端抢票框架的配置、提速与避坑全记录

大麦自动抢票开源项目实战:Selenium+Appium 双端抢票框架的配置、提速与避坑全记录

大麦自动抢票开源项目实战:SeleniumAppium 双端抢票框架的配置、提速与避坑全记录 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 如果你…

2026/8/14 6:09:01 阅读更多 →
Git 403错误全解析:从认证失效到权限不足的排查与修复指南

Git 403错误全解析:从认证失效到权限不足的排查与修复指南

1. 问题引入:当Git对你关上大门 “git The requested URL returned error: 403”。如果你在推送代码到远程仓库,或者拉取私有仓库时,屏幕上突然跳出这行红字,心里多半会咯噔一下。这个403错误,本质上是一个HTTP状态码&…

2026/8/14 6:08:01 阅读更多 →

日新闻

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

临沂网站建设铭镇:深耕本土数字生态,以匠心铸就企业品牌核心竞争力

在这个流量为王、视觉至上的互联网时代,对于临沂乃至整个山东乃至全国的传统中小企业来说,拥有一张精美的“数字名片”早已不再是可选项,而是生存的必答题。每当夜幕降临,沂河两岸灯火辉煌,物流之都的喧嚣逐渐沉淀为对未来的思考。我们常常听到老板们在茶余饭后探讨:为什…

2026/8/14 0:00:26 阅读更多 →
Flutter与OpenHarmony实现剧本杀组队表单开发实战

Flutter与OpenHarmony实现剧本杀组队表单开发实战

1. 项目概述在移动应用开发领域,跨平台框架Flutter因其高效的开发体验和出色的性能表现,已经成为众多开发者的首选。而OpenHarmony作为新兴的操作系统平台,其开放性和灵活性为开发者提供了全新的可能性。本文将聚焦于一个实际应用场景——剧本…

2026/8/14 0:00:26 阅读更多 →
大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

大连网站建设找简维科技:为您打造懂业务更懂用户的数字化转型引擎

在这个数字化浪潮席卷全球的今天,企业想要在激烈的市场竞争中站稳脚跟,拥有一张好看的“数字名片”已经远远不够了。很多老板在刚开始接触互联网业务时,都有一个共同的困惑:为什么我花了钱建的网站,就像是在真空中自嗨?访客进来转了两圈就跑了,线索石沉大海,甚至连客服…

2026/8/14 0:01:27 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/13 10:41:52 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/13 10:41:50 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/13 10:41:49 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/13 10:41:49 阅读更多 →