单源最短路--SPFA算法--邻接链表

package com.xjj.lanqiao;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

import javax.swing.plaf.metal.MetalIconFactory.FolderIcon16;
/*-----求-单源最短路-的SPFA算法-----
 * 1.给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,
 * 2.设立一个先进先出的队列q用来保存待优化的结点,优化时每次取出队首结点u,
 * 	   并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,
 *   如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。
 *   这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
 * 
 * 3.dis[j]>dis[i]+w[i,j]
 * 
 * 4.样例输入
	3 3
	1 2 -1
	1 3 2
	2 3 -1
	样例输出
	-1
	-2
 * 
 * 5.此为邻接链表实现
 * 6.必须将带求节点放在第一个
 * */
public class Spfa {
	//邻接表的形式创建图
	static class edge{
		public int start;
		public int end;
		public int value;
		
		public edge(int a, int b, int value) {
			start = a; 
			end = b;
			this.value = value;
		}
	}
	
	//spfa算法
	public static void spfa(ArrayList<edge>[] lists, int n){
		//dis[i]
		long[] dis = new long[n+1];
		for(int i = 1; i <= n; i++)
			dis[i] = Integer.MAX_VALUE;
		//自己到自己为0
		dis[1] = 0;
		
		//创建队列,		队列用来保存待优化的结点,优化时每次取出队首结点u
		LinkedList<Integer> list = new LinkedList<>();
		list.add(1);
		
		//判断队列是否为空
		while(list.size() > 0){
			//取队首元素,对其他边的权值
			int start = list.getFirst();
			for(int i = 0; i < lists[start].size(); i++){
				int end = lists[start].get(i).end;
				int value = lists[start].get(i).value;
				
				//将start作为中介,松弛
				if (dis[end] > dis[start] + value) {
					dis[end] = dis[start] + value;
					if (!list.contains(end)) {
						list.add(end);
					}
				}
			}
			
			list.removeFirst();
		}
		//到其他顶点
		for(int i = 2; i < n+1; i++)
			System.out.println(dis[i]);
	}

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		//List<ArrayList<edge>> lists = new ArrayList<>();
		//ArrayList<edge> list = new ArrayList<>();
		//n = 节点数,m = 边数
		int n = scanner.nextInt();
		int m = scanner.nextInt();
		
		//告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。
		@SuppressWarnings("unchecked")			
		ArrayList<edge>[] list = new ArrayList[n+1];
		//以数组的形式
		for(int i = 1; i <= n; i++)
			list[i] = new ArrayList<edge>();
		
		for(int i = 1; i  <= m; i++){
			int a = scanner.nextInt();
			int b = scanner.nextInt();
			int value = scanner.nextInt();

			//当a相同时,类似:1 2 -1, 1 3 2;	size为2
			list[a].add(new edge(a, b, value));
			//lists.add(list);
		}		
		spfa(list, n);

	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值