SW练习_poj2387_迪杰斯特拉

典型的迪杰斯特拉,这个题目有两个坑,看了discuss才AC

1.图是无向的。

2.边有重复的,要取最小的

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.PriorityQueue;

public class Main{

    public static int N;//顶点的个数
    public static int[] shortPathLen ; // 保存start到其他各点的最短路径
    public static LinkedList<Edge2387> [] list;
    static int _MAX=2087654321;

    public static void main(String[] args) throws Exception{
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        String[] str=reader.readLine().split(" ");

        int T=Integer.parseInt(str[0]);//第一个是边数
        N=Integer.parseInt(str[1])+1;//第二个是顶点个数
        list=new LinkedList[N];
        for (int i = 0; i < N; i++) {
            list[i]=new LinkedList<Edge2387>();
        }

        for (int i = 0; i < T; i++) {
            str=reader.readLine().split(" ");
            int start=Integer.parseInt(str[0]);
            int to=Integer.parseInt(str[1]);
            int dis=Integer.parseInt(str[2]);
            list[start].add(new Edge2387(start,to,dis));
            list[to].add(new Edge2387(to,start,dis));
        }

        shortPathLen=new int[N];
        for(int i=0;i<shortPathLen.length;i++){
            shortPathLen[i]=_MAX;
        }
        int begin=1;
        proceeDS(list,begin);
        System.out.println(shortPathLen[N-1]);
        reader.close();

    }
    public static void proceeDS(LinkedList<Edge2387> [] list,int begin){//begin 代表起点
        shortPathLen[begin]=0;
        PriorityQueue<Edge2387> pq=new PriorityQueue<Edge2387>();
        Edge2387 e=new Edge2387(begin,begin,0);
        pq.add(e);

        while( ! pq.isEmpty() ){
            Edge2387 startEdge=pq.poll();//弹出最小的路径(不是点),初始情况可以理解为自己到自己
                for (Edge2387 et:list[startEdge.to]) {// 这条路径被选择后,这条路径的终结点相连的路径也要被加进来,然后下一轮继续,et是终结点相连的边
                    if( shortPathLen[et.to]>shortPathLen[et.start]+et.dis) {//能松弛的才需要加入进来
                        shortPathLen[et.to] = shortPathLen[et.start] + et.dis;//松弛操作
                        pq.add(et);
                    }

                }
        }
    }
}

class Edge2387 implements Comparable<Edge2387> {
    public Edge2387( int start,int to, int dis) {
        this.start=start;
        this.to = to;
        this.dis = dis;
    }
    public int to;
    public int dis;
    public int start;
    @Override
    public int compareTo(Edge2387 o) {
        return this.dis-o.dis;
    }
}

 

这个题目使用二维矩阵也能过

package info.frady.algo;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * meng3.wei 20200426
 * 基本的迪杰斯特拉
 */
public class POJ2387 {

    public static final int M = 1000000000; // 代表正无穷
    public static int n;//顶点的个数
    public static int[] shortPathLen ; // 保存start到其他各点的最短路径
    public static boolean [] visited;
    public static int[] pid;

    public static void main(String[] args) throws Exception{
        // 二维数组每一行分别是 A、B、C、D、E 各点到其余点的距离,
        // A -> A 距离为0, 常量M 为正无穷
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        String[] str=reader.readLine().split(" ");

        int T=Integer.parseInt(str[0]);//第一个是边数
        n=Integer.parseInt(str[1])+1;//第二个是顶点个数
        int[][] weight1 = new int[n][n];
        for (int i = 0; i <n ; i++) {
            for (int j = 0; j <n ; j++) {
                weight1[i][j]=M;
            }
        }
        for (int i = 0; i < T; i++) {
            str=reader.readLine().split(" ");
            int start=Integer.parseInt(str[0]);
            int end=Integer.parseInt(str[1]);
            int len=Integer.parseInt(str[2]);
            if(weight1[start][end]>len ){//注意这块是无向图,并且边要去重
                weight1[start][end]=len;
                weight1[end][start]=len;
            }

        }

        pid=new int[n];
        visited=new boolean[n];
        shortPathLen=new int[n];
        int be=1;

        proceeDS(weight1,be);
        System.out.println(shortPathLen[n-1]);
        /*for (int i = 1; i < n; i++) {
            System.out.println("从" + be + "出发到" + i + "的最短距离为:" + shortPathLen[i]);
            int p=pid[i];
            StringBuffer sb=new StringBuffer();
            sb.append(i);
            while(p!=be){
                sb.append(">--"+p);
                p=pid[p];
            }
            sb.append(">--"+be);
            System.out.println(sb.reverse());
        }*/

        reader.close();

    }
    public static void proceeDS(int[][] weight1,int be){//be代表起点
        pid[be]=be;
        visited[be]=true;
        shortPathLen[be]=0;

        for (int i = 1; i < n-1; i++) {
            int minLen=M;
            int s1=0;
            for (int end = 1; end <n ; end++) {//1.找出距离最小的点s1    这块我其实有个疑问,如果be这个顶点和别的点都不连接,那么这块计算不下去了?
                if(!visited[end]  && weight1[be][end]<minLen ){
                    s1=end;
                    minLen=weight1[be][end];
                }
            }
            shortPathLen[s1]=minLen;
            visited[s1]=true;

            for (int e1 = 1; e1<n ; e1++) {//2.根据s1到它连接的每一个e1,如果 (开始节点->s1)+(s1->e1)<(开始节点->e1) 那么开始节点->e1需要更新一下
                if( !visited[e1] && (weight1[be][s1]+ weight1[s1][e1] <weight1[be][e1]) ){

                    weight1[be][e1]=weight1[be][s1]+ weight1[s1][e1];
                    pid[e1]=s1;

                }
            }
        }

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值