道路建设(最小生成树)

道路建设

题目描述

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

在规划过程中,设计师们已经预算出部分城市之间建设公路的经费需求。现在市长想知道,它能不能将他的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
 
Yes

 
样例输入#2
 
10 2 2
1 2 5
1 2 15
 
样例输出#2
 
Yes

数据范围

对于100%的数据,保证 c<1000000,n<10000, m<100,0<v1,v2≤m,ℎ<100,且两个城市之间可能存在多条线路。

思路

这题的思路很明显是利用最小生成树的思想,首先通过最小生成树算法(我用的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");


    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值