leetcode2492. 两个城市间路径的最小分数

该问题通过并查集解决,将城市按连通性分组,确保1和n在同组内,求得最小路径分数。代码中创建并查集对象,连接各城市,最后找到与城市1同组的城市,计算最小距离。

题目

给你一个正整数 n ,表示总共有 n 个城市,城市从 1 到 n 编号。给你一个二维数组 roads ,其中 roads[i] = [ai, bi, distancei] 表示城市 ai 和 bi 之间有一条 双向 道路,道路距离为 distancei 。城市构成的图不一定是连通的。

两个城市之间一条路径的 分数 定义为这条路径中道路的 最小 距离。

城市 1 和城市 n 之间的所有路径的 最小 分数。

注意:

一条路径指的是两个城市之间的道路序列。

一条路径可以 多次 包含同一条道路,你也可以沿着路径多次到达城市 1 和城市 n 。

测试数据保证城市 1 和城市n 之间 至少 有一条路径。

问题解析

这个题目实际上就是连通图分组的问题。根据各个点的连通关系,可以把原始图分成若干个连通图。又因为题目里说“保证城市 1 和城市n 之间 至少 有一条路径”,所以1,n一定在一个连通图里,那么此时这个图里的最短路径就是问题答案。

所以思路到这就比较明确了,可以用并查集的思想,把原始图做分组,然后找到1所在的组,求得最小值。

代码实现

import java.util.*;

class Solution {
    public int minScore(int n, int[][] roads) {
        UnionFind unionFind = new UnionFind(n);
        for(int i=0;i<n;i++){
            unionFind.add(i);
        }
        for(int i=0;i<roads.length;i++){
            int [] disArr = roads[i];
            int start = disArr[0];
            int end = disArr[1];
            //各自所属的集合,不是同一个,那就把这俩合并
            if(!unionFind.isConnected(start-1,end-1)){
                unionFind.merge(start-1,end-1);     
            }
        }
        int minDis = 1000000;
        for(int i=0;i<roads.length;i++){
            int [] disArr = roads[i];
            int start = disArr[0];
            int end = disArr[1];
            int dis = disArr[2];
            //只要判断start,end中的一个即可
            if(unionFind.isConnected(0,start-1)){
                minDis = Math.min(minDis,dis);
            }
        }
        return minDis;
    }
}

//并查集类
class UnionFind {
    //
    private int[] father;
    private int size;

    public UnionFind(int n){
        father = new int[n];
        size = 0;
    }

    //初始化的时候,每个人的父亲是自己
    public void add(int x){
        father[x] = x;
        size ++;
    }

    //找祖宗,找的过程也会重新赋值
    public int findFather(int x){
        if(father[x]!=x){
            father[x] = findFather(father[x]);
        }
        return father[x];
    }
    //把两个集合合并在一起,选出新的父亲
    public void merge(int x,int y){
        int xFather = findFather(x);
        int yFather = findFather(y);
        //直接把x合并到y的集合中。也就是把x的祖宗,指向y的祖宗
        if(xFather != yFather){
            father[xFather] = yFather;
            size--;
        }
    }
    //判断祖宗是否一样
    public boolean isConnected(int x,int y){
        return findFather(x) == findFather(y);
    }
}

在C语言里,位左对齐右对齐一般在格式化输出时会用到,主要用于控制数据在输出时的位置。以下是相关介绍: ### 整型数据的左对齐右对齐 通过`printf`函数实现整型数据的左对齐右对齐右对齐是默认方式,在格式说明符`%`和`d`之间添加数字来规定输出宽度,若数字位数小于规定宽度,会在左边补空格;左对齐则需在数字前加`-`号,若数字位数小于规定宽度,会在右边补空格。 示例代码如下: ```c #include <stdio.h> int main() { // 右对齐。数字宽度为10,若不足10,在左边补足空格 printf("%10d\n", 1234); // 左对齐。数字宽度为10,若不足10,在右边补足空格 printf("%-10d\n", 1234); return 0; } ``` ### 不同输出长度的情况 当规定的输出宽度和数字实际位数不同时,有不同的处理方式。若规定宽度小于数字实际位数,会完整输出数字;若规定宽度大于数字实际位数,右对齐在左边补空格,左对齐在右边补空格。 示例代码如下: ```c #include <stdio.h> int main() { // -5是左对齐,输出长度为5。5是右对齐,输出长度为5 printf("%-5d %5d\n", 455, 455); printf("%-5d %5d\n", -123, -123); // 规定宽度小于实际位数,完整输出数字 printf("%-5d %5d\n", 987654, 987654); return 0; } ``` ### 其他数据类型的对齐 除整型外,其他数据类型也能实现左对齐右对齐。例如浮点数(`%f`)、字符串(`%s`)等,方法和整型一致。 示例代码如下: ```c #include <stdio.h> int main() { // 右对齐浮点数,宽度为10 printf("%10f\n", 3.14); // 左对齐浮点数,宽度为10 printf("%-10f\n", 3.14); // 右对齐字符串,宽度为10 printf("%10s\n", "hello"); // 左对齐字符串,宽度为10 printf("%-10s\n", "hello"); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值