• 道路建设(最小生成树)


    道路建设

    题目描述

    随着如今社会的不断变化,交通问题也变得越来越重要,所以市长决定建设一些公路来方便各个城市之间的贸易和交易。虽然市长的想法很好,但是他也遇到了一般人也经常头疼的问题,那就是手头的经费有限……

    在规划过程中,设计师们已经预算出部分城市之间建设公路的经费需求。现在市长想知道,它能不能将他的m 个城市在有限的经费内实现公路交通。如果可以的话,输出Yes,否则输出No(两个城市不一定要直接的公路相连,间接公路到达也可以。)

    输入格式

    测试输入包含多条测试数据。

    每个测试数据的第 1 行分别给出可用的经费 c,道路数目 n,以及城市数目 m。接下来的 n 行给出建立公路的成本信息,每行给出三个整数,分别是相连的两个城市 v 1 、v 2 以及建设公路所需的成本 h。

    输出格式

    对每个测试用例,输出 Yes 或 No。

    样例输入输出

    样例输入#1
     
    20 10 5
    1 2 6
    1 3 3
    1 4 4
    1 5 5
    2 3 7
    2 4 7
    2 5 8
    3 4 6
    3 5 9
    4 5 2
    
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    样例输出#1
     
    Yes
    
     
    
    • 1
    • 2
    • 3
    • 4
    样例输入#2
     
    10 2 2
    1 2 5
    1 2 15
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    样例输出#2
     
    Yes
    
    
    • 1
    • 2
    • 3

    数据范围

    对于100%的数据,保证 c<1000000,n<10000, m<100,0

    思路

    这题的思路很明显是利用最小生成树的思想,首先通过最小生成树算法(我用的prim算法)计算出要花的经费,再与题干中的经费c对比大小,如果比c小就说明有方案Yes,否则就是No。具体实现思路在代码备注中。

    
    
    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Scanner scanner=new Scanner(System.in);
            Long c=scanner.nextLong();
            int n=scanner.nextInt();
            int m=scanner.nextInt();
            int [][]city=new int[m+1][m+1];//地图数组
            //初始化city,初始都是100,也就是正无穷,不可达
            for(int i=0;i<m;++i){
                for(int j=0;j<m;++j){
                    city[i][j]=100;
                }
            }
            //根据输入设置city的初始化值
            for(int i=0;i<n;++i){
                //因为题干中是从1开始的,但是数组是从0开始的,所以每个都要-1
                int x=scanner.nextInt()-1;
                int y=scanner.nextInt()-1;
                int h=scanner.nextInt();
                //因为题干中说了每个城市之间有不同的路线,所以在city数组中只保存最小的路线
                if(city[x][y]>h){
                    city[x][y]=h;
                    city[y][x]=h;
                }
    
            }
            //vis表示哪些结点访问过
            boolean []vis=new boolean[m];
            //初始只有0结点访问过
            for (int i=0;i<m;++i){
                vis[i]=false;
            }
            vis[0]=true;
            //利用prim最小生成树来做,寻找每次的最小权重的值,
            // 为了防止寻找到的边会组成圈,所以在邻接矩阵中已访问的结点中的边寻找最小边
            // 并且最小边满足列中对应的结点在vis没有访问过,而行在vis中访问过,按照这样寻找到的最小边就是不会成圈的边
            for (int i=0;i<m-1;++i){
                int min=101;
                int node=m+1;
                for (int j=0;j<m&&vis[j];++j){
                    for (int k=0;k<m;++k){
                        if(vis[k]) continue;
                        if(min>city[j][k]){
                            min=city[j][k];
                            node=k;
                        }
                    }
                }
                // 把寻找到的最小边对应的结点放进vis中
                vis[node]=true;
                // 没找到一个最小边就去减经费c,如果最后c大于零说明有方案,否则就没有方案
                c-=min;
    
            }
            if(c>=0) System.out.println("Yes");
            else System.out.println("No");
    
    
        }
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
  • 相关阅读:
    redis快速入门
    网上买的流量卡说3个月后才能开通通话功能,这到底是为什么呢?
    Flutter桌面开发 — macOS平台App打包上架发布AppStore
    margin的塌陷现象
    归纳所猜半结论推出完整结论:CF1592F1
    使用 pair 做 unordered_map 的键值
    华清 c++ day3 9月10
    《传习录》读书笔记(一)
    zeus平台常见故障及排查方法
    shiro授权-SSM
  • 原文地址:https://blog.csdn.net/WUHU648/article/details/134545942