单源最短路径Dijkstra算法(java实现)

一直没写过Dijkstra算法,都是停留在理论中,这次终于写了一个,当然也参考了其他人的code,但是毕竟还是从code上面又进步了,继续刷题~~~


1、牛客网题目:

原来是要到醋溜站台乘坐醋溜快车到醋溜港”,亮亮解出了地图隐藏的秘密,赶紧奔向醋溜站台,但到了之后,亮亮忧桑地发现,从醋溜站台到醋溜港沿途的每个车站都有很多美女被他飒爽的英姿所吸引,只要经过车站就会被这些漂亮的女孩搭讪,但是现在亮亮一心想要寻找楚楚街而没空去搭理她们,所以亮亮希望在抵达醋溜港的时候被搭讪的次数最少。问亮亮抵达醋溜港最少会被搭讪多少次?

输入描述:

第一行包含两个整数N(2<=N<=5000),M(1<=M<=50000)。N表示公有N个汽车站,M表示公有M条公路,起点为1,终点为N。 第二行包含N个整数(0<=K<=10000),第i个整数表示在第i站有K个美女想要搭讪亮亮。 接下来M行,每行包含两个整数P(1<=P<=N),Q(1<=Q<=N),代表P,Q两个站是有班车直达的。

输出描述:

一个整数,即亮亮抵达醋溜港最少需要被搭讪的次数。
示例1

输入

5 5
0 1 1 3 6
1 2
1 4
2 3
3 5
4 5

输出

8



2、code实现:已ac

package schooloffer;

import java.util.Scanner;

/**
 * Created by caoxiaohong on 17/9/21.
 * 原来是要到醋溜站台乘坐醋溜快车到醋溜港”,亮亮解出了地图隐藏的秘密,赶紧奔向醋溜站台,但到了之后,亮亮忧桑地发现,
 * 从醋溜站台到醋溜港沿途的每个车站都有很多美女被他飒爽的英姿所吸引,只要经过车站就会被这些漂亮的女孩搭讪,但是现在亮亮一心想要寻找楚楚街而没空去搭理她们,
 * 所以亮亮希望在抵达醋溜港的时候被搭讪的次数最少。问亮亮抵达醋溜港最少会被搭讪多少次?
 *
 * 一直ac不过,原来是因为:本题是做无向图处理的,而我当作有向图处理了.所以,添加了第34行代码,就ac了.
 */
public class Trival {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        while (scanner.hasNext()){
            int N=scanner.nextInt();//N个站台
            int M=scanner.nextInt();//M条公路
            int[] tmp=new int[N+1];//每个站台的搭讪美女个数
            for(int i=1;i<=N;i++)
                tmp[i]=scanner.nextInt();
            int[][] weights=new int[N+1][N+1];
            //初始化无穷大
            for(int i=1;i<=N;i++){
                for(int j=1;j<=N;j++)
                    weights[i][j]=Integer.MAX_VALUE;
            }

            for(int i=0;i<M;i++){
                int from=scanner.nextInt();
                int to=scanner.nextInt();
                //因是无向图,所以权重同时有2个被赋值
                weights[from][to]=tmp[to];//这里只是记录了从a到b时候,b的权重,作为边的权重.所以最后整条路径上,自然找了起点的权重.故最后输出结果必须加上起点的权重.
                weights[to][from]=tmp[from];
            }
            System.out.println(dijkstra(weights,1)+tmp[1]);
        }
    }

    /**
     * 单源最短路径
     * @param weights 权重矩阵
     * @param start 开始节点编号
     * @return
     */
    private static int dijkstra(int[][] weights,int start){
        int n=weights.length;//顶点个数+1
        int[] dist=new int[n]; //保存:从start出发,到其他各个顶点的最短路径
        boolean[] isVisited=new boolean[n];//记录节点的最短路径是否已经求出,true表示已经求出
        //初始化第一个节点
        dist[1]=0;
        isVisited[1]=true;

        int k;
        for(int i=2;i<n;i++){ //需要访问所有节点
            k=-1;
            int minValue=Integer.MAX_VALUE;
            for(int j=1;j<n;j++){ //查找一个距离start最近的节点
                if(!isVisited[j] && weights[start][j]<minValue){
                    k=j;
                    minValue=weights[start][j];
                }
            }
            /**注意:如果是有向图,可能出现情况:就是n个节点并没有遍历完,但是已经找不到:节点既未被遍历同时,由当前已经遍历的节点能到达这些未 被遍历的点.说明这些点,是无法到达的
             * 当然了,本题是无向图,这种情况是不会出现的。
             */
            if(k==-1)
                break;
            //修改节点k的值
            dist[k]=minValue;
            isVisited[k]=true;

            //修改其他未访问节点,在经过中间节点k后,新的最短路径
            for(int j=1;j<n;j++){
                if(!isVisited[j] &&  weights[k][j]!=Integer.MAX_VALUE &&  weights[start][k]+weights[k][j]<weights[start][j] ){
                    weights[start][j]=weights[start][k]+weights[k][j];
                }
            }
        }
        return weights[start][n-1];
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值