【最短路】·SPFA算法实现

 感谢caioj scy老师通俗易懂的讲解,非常可惜小白菜要注销了,学oi太晚,还妹有来得及做多少里面的题,遗憾。

(题目是caioj1088)

 

#include<cstdio>
#include<cstring>
using namespace std;
struct bian//表示有向边的结构体,构建编目录
{
    int x,y,d,next;// x表示出发点,y表示终点,next表示和x相连的上一条边的编号
};
 
bian a[210000]; 

int len,n,last[11000];//a的个数是边的个数,last的个数是点的个数。
 
//last[i]表示最后一条和点i相连的边的编号。
int d[11000];//d[i]表示目前i和出发点的最短距离
int list[11000],head,tail;//list用来存排队准备更新其他人的点,head表示头,tail表示尾
void ins(int x,int y,int d)// ins函数的功能是建立一条边
{
    len++;//全局增加一条有向边,len一开始为0
    a[len].x=x; a[len].y=y;a[len].d=d;//边的赋值
    a[len].next=last[x]; last[x]=len;//边的联系  (顺序不可以变,是为了遍历所有与某一点的边) 
}

bool v[11000];// v[i]等于true表示点i在队列list中,等于false表示点i不再队列list中
int main()
{ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int x,y,c,m,st,ed; scanf("%d%d",&n,&m); len=0; memset(last,0,sizeof(last));//注意构图之前一定要初始化,不然后果很严重! for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&c);//题目给出的是无向边,而我们的边目录是有向边 ins(x,y,c);//建立正向边 ins(y,x,c);//建立反向边 } //1:初始化d,这样后面才有更新的必要 st=1;ed=n; for(int i=1;i<=n;i++) d[i]=999999999; d[st]=0;//出发点为0 //2:初始化v, 一开始所有点都没有 memset(v,false,sizeof(v)); v[st]=true;//点1作为出发点已经进入list //3:初始化队列list list[1]=st; head=1;tail=2;//队列的头是有人的,队列的尾tail指的位置是没人的 while(head!=tail)//只要头不等于尾,就表示还有人需要更新别人 { x=list[head];//取出准备好更新别人的人x for(int k=last[x]; k ; k=a[k].next )//重点理解!k首相等于和x相连的最后一条边的编号。那么倒数第二条和x相连的边的编号是多少呢?在a[最后一条].next可以找到 { y=a[k].y; if(d[y]>d[x]+a[k].d)//更新是一定要的 { d[y]=d[x]+a[k].d; if(v[y]==false)//如果被更新了,那么要考虑进入队列(考虑是否去更新别人) { v[y]=true; list[tail]=y; tail++; if(tail==n+1) tail=1;//如果tail超过队列的最后一个,则变为第一个 } } } //x已经完成更新别人的任务,就要退出队列list,那么需要做什么呢? list[head]=0; head++; if(head==n+1) head=1; //如果head超过队列的最后一个,则变为第一个 v[x]=false; } printf("%d\n",d[n]);//最后输出终点到出发点的距离 return 0; }

 

转载于:https://www.cnblogs.com/phemiku/p/11389479.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SPFA算法(Shortest Path Faster Algorithm)是一种用于解决最短路问题的算法。它是一种单源最短路算法,可以解决带有负权边的图的最短路径问题。 SPFA算法基本思想是使用队列对图中的所有节点进行遍历,对于每一个节点,如果它的邻居节点的最短路径可以通过当前节点更新,则将邻居节点加入队列中进行下一轮遍历,直到所有节点的最短路径都被更新后停止遍历。 在Java中,可以使用邻接矩阵或邻接表来表示图,并使用队列来实现SPFA算法。下面是一个使用邻接矩阵实现SPFA算法的Java代码示例: ```java import java.util.*; public class SPFA { public static void main(String[] args) { int[][] graph = { {0, 2, 5, Integer.MAX_VALUE, Integer.MAX_VALUE}, {Integer.MAX_VALUE, 0, 7, 1, Integer.MAX_VALUE}, {Integer.MAX_VALUE, Integer.MAX_VALUE, 0, 4, Integer.MAX_VALUE}, {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 0, 3}, {Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} }; int[] dist = shortestPath(graph, 0); System.out.println(Arrays.toString(dist)); } public static int[] shortestPath(int[][] graph, int start) { int n = graph.length; int[] dist = new int[n]; Arrays.fill(dist, Integer.MAX_VALUE); dist[start] = 0; Queue<Integer> queue = new LinkedList<>(); queue.offer(start); boolean[] inQueue = new boolean[n]; inQueue[start] = true; while (!queue.isEmpty()) { int u = queue.poll(); inQueue[u] = false; for (int v = 0; v < n; v++) { if (graph[u][v] != Integer.MAX_VALUE && dist[v] > dist[u] + graph[u][v]) { dist[v] = dist[u] + graph[u][v]; if (!inQueue[v]) { queue.offer(v); inQueue[v] = true; } } } } return dist; } } ``` 在上面的代码中,我们使用一个二维数组`graph`来表示图,其中`graph[i][j]`表示从节点`i`到节点`j`的边的权重,如果没有边则为`Integer.MAX_VALUE`。函数`shortestPath`接受一个图和一个起点`start`,返回一个数组`dist`,其中`dist[i]`表示从起点`start`到节点`i`的最短路径。 在函数中,我们首先初始化`dist`数组为`Integer.MAX_VALUE`,表示所有节点到起点的距离都是无限大。然后将起点`start`加入队列中,并标记为已加入队列。进入循环后,每次取出队列中的一个节点`u`,将`u`标记为未加入队列,然后遍历`u`的所有邻居节点`v`,如果从起点到`v`的距离可以通过从起点到`u`再加上`u`到`v`的距离来更新,则更新`dist[v]`的值,并将`v`加入队列中,并标记为已加入队列。当队列为空时,所有节点的最短路径都已被更新,函数返回`dist`数组。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值