题目链接
题目概述
给定一个包含 n
个城市的图(可能不连通),以及若干双向道路及其距离。定义路径的分数为路径中道路的最小距离,求从城市 1
到城市 n
的所有路径中,分数的最小值。
思路分析
关键点:对于任何路径,其分数由路径中的最小边决定。因此,全局最小分数即为连接城市 1
和 n
的连通分量中所有边的最小值。无论路径如何绕,只要包含这条最小边,分数即为该边值。故问题转化为寻找该连通分量的最小边。
解法步骤
- 预处理邻接边最小值:记录每个节点所有邻接边中的最小值。
- 并查集确定连通分量:合并连通的城市,找到包含
1
和n
的连通分量。 - 遍历连通分量:收集该分量中所有节点的最小邻接边,取全局最小值。
代码解析
class Solution {
public:int minScore(int n, vector<vector<int>>& roads) {unordered_map<int,int>cb;int m=roads.size(),re=1e6;for(auto x:roads){if(cb[x[0]]!=0)cb[x[0]]=min(cb[x[0]],x[2]);else cb[x[0]]=x[2];if(cb[x[1]]!=0)cb[x[1]]=min(cb[x[1]],x[2]);else cb[x[1]]=x[2];}vector<int>p(n+1);for(int i=1;i<=n;i++)p[i]=i;auto fin=[&](auto &&fin,int a){if(p[a]==a)return a;else return p[a]=fin(fin,p[a]);};for(int i=0;i<m;i++){int x=fin(fin,roads[i][0]);int y=fin(fin,roads[i][1]);if(x!=y){p[x]=y;}}for(int i=1;i<=n;i++)fin(fin,i);int tk=fin(fin,n);for(int i=1;i<=n;i++){if(p[i]==tk){re=min(re,cb[i]);}}return re;}
};
代码细节说明
- 预处理邻接边最小值:遍历所有道路,更新每个节点
u
和v
的最小邻接边到cb
中。 - 并查集操作:
- 初始化:每个节点的父节点初始为自身。
- 合并操作:将每条道路的两端点合并,确保连通性。
- 确定连通分量:通过查找
n
的根节点tk
,确定目标连通分量。 - 收集最小值:遍历所有节点,若属于该连通分量,则用其邻接边最小值更新最终结果。
复杂度分析
- 时间复杂度:并查集操作近似 \(O(m \alpha(n))\)(线性),预处理和遍历均为 \(O(m + n)\),整体 \(O(m + n)\)。
- 空间复杂度:\(O(n + m)\),存储并查集父数组和邻接边信息。
结尾
我想出去玩!