单元最短路径

标题: 单元最短路径
时 限: 1000 ms
内存限制: 10000 K
总时限: 3000 ms
描述: 给定一个带权有向图 G=(V,E) ,其中每条边的权是一个整数。另外,还给定 V 中的一个顶点,称为源。现在我们要计算从源到所有其他各顶点的最短路径长度。这里的长度是指路上各边权之和。这个问题通常称为单源最短路径问题.
输入:

第一行为一个整数n,表示包含源在内的顶点的个数,接下来是一个n*n的矩阵,矩阵中-1表示此路不通,否则表示从该顶点到另一顶点的距离。例如对于上图所示的问题我们可以按输入样例中的方式输入。

输出:  
输入样例:  5
-1 10 -1 30 100
-1 -1 50 -1 -1
-1 -1 -1 -1 10
-1 -1 20 -1 60
-1 -1 -1 -1 -1
输出样例:  10 50 30 60
提示:  
来源:  
 
贪心算法
复制代码
import java.util.Scanner;

public class Main {
    static int n = 0;
    static float[] dist = null;
    static int[] prev = null;

    public static void dijkstra(int v, float[][] a, float[] dist, int[] prev) {
        int n = dist.length - 1;

        if (v < 1 || v > n)
            return;
        boolean[] s = new boolean[n + 1];

        for (int i = 1; i <= n; i++) {
            dist[i] = a[v][i];
            s[i] = false;
            if (dist[i] == -1)
                prev[i] = 0;
            else
                prev[i] = v;
        }

        dist[v] = 0;
        s[v] = true;
        for (int i = 1; i < n; i++) {
            float temp = Float.MAX_VALUE;
            int u = v;
            for (int j = 1; j <= n; j++) {
                if (!s[j] && (dist[j] < temp)&&dist[j]!=-1) {
                    u = j;
                    temp = dist[j];
                }
            }
            s[u] = true;
            for (int j = 1; j <= n; j++) {
                if (!s[j] && (a[u][j] != -1)) {
                    float newdist = dist[u] + a[u][j];
                    if (newdist < dist[j]||dist[j]==-1) {
                        dist[j] = newdist;
                        prev[j] = u;
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //System.out.println("请输入顶点个数n");
        Scanner myscanner = new Scanner(System.in);
        n = myscanner.nextInt();
        
        float[][] a = new float[n + 1][n + 1];
        float[] dist = new float[n + 1];
        int[] prev = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                a[i][j] = (float) myscanner.nextInt();
            }
        }
        
        dijkstra(1, a, dist, prev);

        for (int i = 2; i < n; i++) {
            System.out.print((int)dist[i]+" ");
        }
        System.out.println((int)dist[n]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最短路径算法是指在一个加权有向图或者无向图中,从一个源点到所有其他顶点最短路径算法。其中,边的权重必须为非负Java中可以使用Dijkstra算法和Bellman-Ford算法来实现单元最短路径算法。 Dijkstra算法的基本思想是:设立一个集合S,存放已经求得最短路径顶点,以及一个组dist,表示源点到各个顶点的最短距离。初始时,集合S中只有源点,dist组中除了源点为0外,其余元素都为无穷大。然后,每次从dist组中选择最小值对应的顶点,加入集合S中,并更新dist组。具体实现可以使用优先队列来优化时间复杂度。 Bellman-Ford算法的基本思想是:设立一个组dist,表示源点到各个顶点的最短距离,初始时,dist组中除了源点为0外,其余元素都为无穷大。然后,对于每一条边(u,v),如果dist[u]+w(u,v)<dist[v],则更新dist[v]为dist[u]+w(u,v)。重复执行V-1次后,如果还存在dist[u]+w(u,v)<dist[v]的情况,则说明存在负权回路。 下面是Java代码示例: ```java // Dijkstra算法 public void dijkstra(int[][] graph, int src) { int n = graph.length; int[] dist = new int[n]; boolean[] visited = new boolean[n]; PriorityQueue<Integer> pq = new PriorityQueue<>(n, (a, b) -> dist[a] - dist[b]); Arrays.fill(dist, Integer.MAX_VALUE); dist[src] = 0; pq.offer(src); while (!pq.isEmpty()) { int u = pq.poll(); if (visited[u]) { continue; } visited[u] = true; for (int v = 0; v < n; v++) { if (graph[u][v] > 0 && !visited[v] && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; pq.offer(v); } } } } // Bellman-Ford算法 public void bellmanFord(int[][] graph, int src) { int n = graph.length; int[] dist = new int[n]; Arrays.fill(dist, Integer.MAX_VALUE); dist[src] = 0; for (int i = 1; i < n; i++) { for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) { if (graph[u][v] > 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) { dist[v] = dist[u] + graph[u][v]; } } } } for (int u = 0; u < n; u++) { for (int v = 0; v < n; v++) { if (graph[u][v] > 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) { System.out.println("图中存在负权回路"); return; } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值