news 2026/6/15 20:15:09

繁忙的都市(city)(信息学奥赛一本通- P1392)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
繁忙的都市(city)(信息学奥赛一本通- P1392)

【题目描述】

城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造。城市C的道路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连接。这些道路是双向的,且把所有的交叉路口直接或间接的连接起来了。每条道路都有一个分值,分值越小表示这个道路越繁忙,越需要进行改造。但是市政府的资金有限,市长希望进行改造的道路越少越好,于是他提出下面的要求:

1.改造的那些道路能够把所有的交叉路口直接或间接的连通起来。

2.在满足要求1的情况下,改造的道路尽量少。

3.在满足要求1、2的情况下,改造的那些道路中分值最大值尽量小。

作为市规划局的你,应当作出最佳的决策,选择那些道路应当被修建。

【输入】

第一行有两个整数n,m表示城市有n个交叉路口,m条道路。接下来m行是对每条道路的描述,u, v, c表示交叉路口u和v之间有道路相连,分值为c。(1≤n≤300,1≤c≤10000)。

【输出】

两个整数s, max,表示你选出了几条道路,分值最大的那条道路的分值是多少。

【输入样例】

4 5 1 2 3 1 4 5 2 4 7 2 3 6 3 4 8

【输出样例】

3 6

1. 算法分析

这道题看似需要一种特殊的“瓶颈”算法,但实际上,最小生成树 (MST) 本身就满足这个性质

  • MST 的定义是总权值和最小。

  • 推论:MST同时也满足树中最大边权最小

因此,我们只需要跑一遍标准的MST算法(Kruskal或Prim),然后找出树中权值最大的那条边即可。


2. 解法一:Kruskal 算法 (推荐)

核心思路:

Kruskal 算法将所有边按权值从小到大排序。

当我们贪心地选取边加入集合时,最后加入的那条边(第N-1条边),一定是当前生成树中权值最大的边。

代码亮点:

直接输出 mst[cnt].w,无需再次遍历寻找最大值。

//kruskal 核心:排序后,最后加入生成树的边,即为最大权值边。 #include <iostream> #include <algorithm>//sort using namespace std; int n,m; struct edge{ int u,v,w; //重载运算符,按边权从小到大排序 friend bool operator <(edge a,edge b){ return a.w<b.w; } }e[10010];//边集数组 edge mst[10010];//存最小生成树有多少条边 int cnt;//最小生成树边数 long long sum;//最小生成树的长度 int fa[310];//记录每个节点所在集合中的老大 //并查集查询+路径压缩 int find(int x){ if(fa[x]==x) return x;//如果是根节点就返回 //不是就递归找根节点,并把根节点赋给沿途所有节点 return fa[x]=find(fa[x]); } //合并 void uni(int a,int b){ int faa=find(a); int fab=find(b); if(faa!=fab){ fa[fab]=faa; } } void kruskal(){ for(int i=1;i<=m;i++){ int a=e[i].u;//边集数组第i条边一个端点 int b=e[i].v;//边集数组第i条边另外一个端点 if(find(a)!=find(b)){//如果两个端点不在一个集合就链接他们 cnt++; mst[cnt].u=a; mst[cnt].v=b; mst[cnt].w=e[i].w; sum+=e[i].w; uni(a,b); } } } int main(){ cin>>n>>m; //初始化边集数组自成集合,每个点是自己的老大 for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++){ cin>>e[i].u>>e[i].v>>e[i].w; } //对边集数组按边权从小到大排序 sort(e+1,e+m+1); kruskal(); cout<<cnt<<" "<<mst[cnt].w; }

3. 解法二:堆优化Prim算法

核心思路:

Prim算法通过优先队列每次选择离集合最近的点。

我们需要一个变量ma来记录入队并被选中的边的最大值。

每当一个点被正式加入集合(vis[nid]=1)时,更新 ma=max(ma, dis[nid])。

代码技巧:

cnt 初始化为 -1。因为起点加入集合时不算边,这样当跑完所有点后,cnt 刚好是N-1。

//prim+堆优化 #include <iostream> #include <cstring>//对应memset #include <algorithm>//对应max函数 #include <queue> using namespace std; int n,m; int h[310];//邻接表头指针数组 int vtex[20010];//第i条边的终点下表 int nxt[20010];//与第i条边同起点的下一条边的索引 int wt[20010];//第i条边的边权 int idx; int vis[310];//标记每个点是否已经连通(加入集合) int dis[310];//记录每个点到集合的距离 int cnt=-1;//记录连接上的边数 cnt初始化为-1,就是因为第一个点加入集合不需要边 int ma=0;//记录分值最大的那条道路的分值 long long sum;//最小生成树的总长度 struct node{ int id;//节点编号 int w;//节点权值 //优先队列默认最大堆,重载运算符改为最小堆 离集合最近的点优先出队 friend bool operator<(node a,node b){ return a.w>b.w; } }; priority_queue<node> q; void prim(int s){ dis[s]=0;//起点到自己距离为0 node tmp; tmp.id=s; tmp.w=0; q.push(tmp);//起点入队 while(!q.empty()){ tmp=q.top();//访问队首元素 q.pop();//队首出队 int nid=tmp.id; //如果tmp已经加入集合(出队过)就跳过 if(vis[nid]==1) continue; vis[nid]=1;//否则就链接上 cnt++;//cnt初始化为-1,就是因为第一个点加入集合不需要边 sum+=dis[nid]; ma=max(ma,dis[nid]); int p=h[nid]; while(p!=-1){//遍历tmp的所有邻接点 //如果该临接点尚未加入集合 且目前到集合距离大于经tmp到集合距离 就更新到集合距离 //为经tmp到集合距离 if(vis[vtex[p]]==0 && dis[vtex[p]]>wt[p]){ dis[vtex[p]]=wt[p]; q.push({vtex[p],wt[p]});//然后把这个点入队 } p=nxt[p];//更新指针 } } } void addedge(int u,int v,int w){ vtex[idx]=v; wt[idx]=w; nxt[idx]=h[u]; h[u]=idx++; } int main(){ cin>>n>>m; memset(h,-1,sizeof(h));//初始化头指针数组为空 memset(dis,0x3f,sizeof(dis));//初始化每个点到集合距离为无穷 //邻接表存图 for(int i=1;i<=m;i++){ int u,v,w; cin>>u>>v>>w; addedge(u,v,w);//双向边 addedge(v,u,w); } prim(1);// cout<<cnt<<" "<<ma; return 0; }

4. 总结

算法核心逻辑获取最大边的方式推荐指数
Kruskal边排序+并查集直接取最后一条加入的边 (mst[cnt].w)⭐⭐⭐⭐⭐ (最直观)
Prim优先队列+贪心过程中维护max⭐⭐⭐⭐ (适合稠密图)

这两份代码都已通过测试,是标准的算法模板。对于“瓶颈生成树”类问题,Kruskal 通常更简单直观,因为它天然基于边权排序。

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

低成本GPU部署:DeepSeek-R1-Distill-Qwen-1.5B在T4上的表现评测

低成本GPU部署&#xff1a;DeepSeek-R1-Distill-Qwen-1.5B在T4上的表现评测 1. 背景与选型动机 随着大模型在实际业务场景中的广泛应用&#xff0c;如何在有限硬件资源下实现高效推理成为工程落地的关键挑战。NVIDIA T4作为一款广泛部署的中端GPU&#xff0c;凭借其16GB显存和…

作者头像 李华
网站建设 2026/6/15 14:17:34

G2P:英语文字转音素神器完全使用手册

G2P&#xff1a;英语文字转音素神器完全使用手册 【免费下载链接】g2p g2p: English Grapheme To Phoneme Conversion 项目地址: https://gitcode.com/gh_mirrors/g2/g2p 还在为英语单词发音发愁吗&#xff1f;G2P这个神奇的Python工具能帮你把文字完美转换为音素&#…

作者头像 李华
网站建设 2026/6/15 15:21:46

零基础玩转Open Interpreter:Qwen3-4B本地代码生成实战

零基础玩转Open Interpreter&#xff1a;Qwen3-4B本地代码生成实战 1. 引言&#xff1a;为什么需要本地AI编程助手&#xff1f; 在大模型时代&#xff0c;自然语言驱动代码生成已成为现实。OpenAI 的 Code Interpreter 曾经引领了这一潮流&#xff0c;但其运行在远程沙箱中&a…

作者头像 李华
网站建设 2026/6/15 14:21:38

洛雪音乐全网音源配置完整教程:快速解锁海量音乐资源

洛雪音乐全网音源配置完整教程&#xff1a;快速解锁海量音乐资源 【免费下载链接】lxmusic- lxmusic(洛雪音乐)全网最新最全音源 项目地址: https://gitcode.com/gh_mirrors/lx/lxmusic- 还在为洛雪音乐搜不到歌曲而困扰吗&#xff1f;掌握正确的音源配置方法&#xff0…

作者头像 李华
网站建设 2026/6/15 14:09:48

G2P:文字转音素终极指南,让机器学会“说人话“ [特殊字符]

G2P&#xff1a;文字转音素终极指南&#xff0c;让机器学会"说人话" &#x1f3af; 【免费下载链接】g2p g2p: English Grapheme To Phoneme Conversion 项目地址: https://gitcode.com/gh_mirrors/g2/g2p 你是否曾经好奇语音助手是如何将文字转换成自然流畅的…

作者头像 李华
网站建设 2026/6/15 16:00:49

Wan2.2视频大模型:MoE技术让AI视频创作提速增效

Wan2.2视频大模型&#xff1a;MoE技术让AI视频创作提速增效 【免费下载链接】Wan2.2-T2V-A14B 项目地址: https://ai.gitcode.com/hf_mirrors/Wan-AI/Wan2.2-T2V-A14B 导语&#xff1a;Wan2.2视频大模型正式发布&#xff0c;凭借创新的MoE&#xff08;Mixture-of-Exper…

作者头像 李华