PowerOJ 1799(spfa求最短路+路径输出)

  • 西科大新成立了一个WS旅行社。现在在全校范围内招收导游,旅行社为前来应聘的同学设计了一道难题:给应聘者一张地图,看他能否很快的计算出从出发点到达终点的最短路径,这个问题,相信对于来自西科大的你来说,是轻而易举的事情,但是作为旅行社的社长,Bearboy 还要求应聘者能够在地图中画出这条最短路。
  • Input
  •  
  • 输入的第一行为一个整数T(T组测试数据<=100)
  • 对于每一组测试数据,第一行为两个整数 N,M。N表示地图上的景点个数(N<=2000)。(1 . 2 . 3....N),M表示道路个数。接下来是M行,每行包括三个整数 S .T .L,表示 景点S与景点T之间的距离是L(L<=1000)
  • 最后一行是两个整数st 和 en ,表示旅行的 起点 和 目的地。
  • Output
  •  
  • 对于每组测试数据,输出包括两行,第一行是从st到en的最短路径长度。
  • 第二行是输出从起点到目的地所经过的所有景点(如Sample output所示) 以先后顺序输出,数据保证只有一条最优路径
  • 如果不能到达就输出 none!
  • 每组测试数据后输出一个空行。
  • Sample Input
  • Raw
  • 1
  • 5 8
  • 1 2 1
  • 1 4 10
  • 2 3 5
  • 2 4 1
  • 2 5 12
  • 3 4 1
  • 3 5 1
  • 5 4 8
  • 1 5
  • Sample Output
  • Raw
  • Case 1 : 4
  • 1 2 4 3 5
  • 感谢万能的火山哥。
  • 代码:
  • #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2005;
    const int INF=0x7FFFFFFF;//无穷大
    int pre[maxn];//记录一个前驱
    int dis[maxn];//记录距离
    int path[maxn];//记录路径
    bool vis[maxn];//标记点
    int head[maxn];//存边
    int n,m;
    int tot,cnt;
    /*struct node//两种方法建立邻接表存图
    {
        int v,w,next;
        node(){}
        node(int v,int w,int next):v(v),w(w),next(next){}
    }E[maxn*maxn];
    void add(int u,int v,int w)
    {
        E[tot]=node(v,w,head[u]);
        head[u]=tot++;
    }*/
    struct node
    {
        int v,w,next;
    }E[maxn*maxn];
    void add(int u,int v,int w)
    {
        E[tot].v=v;
        E[tot].w=w;
        E[tot].next=head[u];
        head[u]=tot++;
    }
    void init()
    {
        tot=0;
        memset(vis,false,sizeof((vis)));
        memset(head,-1,sizeof(head));
    }
    void spfa(int st)
    {
        for(int i=1;i<=n;i++)
        {
            vis[i]=false;
            dis[i]=INF;
        }
        queue<int>q;
        q.push(st);
        int now,next;
        dis[st]=0;
        vis[st]=true;
        pre[st]=-1;
        while(!q.empty())
        {
            now=q.front();
            q.pop();
            vis[now]=false;//对于弹出队列的就不需要再进入队列了
            for(int i=head[now];i!=-1;i=E[i].next)
            {
                next=E[i].v;
                if(dis[next]>dis[now]+E[i].w)//类似于三角形两边之和大于第三边,是不是就走距离短的那边了
                {
                    dis[next]=dis[now]+E[i].w;
                    pre[next]=now;//需要记录一下这个点的前驱,对于输出路径有用
                    if(!vis[next])//如果这点不在队列里面,就把他加如队列然后再找,就这样一直找
                    {
                        vis[next]=true;
                        q.push(next);
                    }
                }
            }
        }
    }
    void print(int x)//递归输出路径,每次找到当前点的前驱就可以了
    {
        if(pre[x]==-1) return;
        print(pre[x]);
        path[++cnt]=x;//放在后面是正着存的,输出就是正着输出的
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++)
        {
            init();
            scanf("%d%d",&n,&m);
            int u,v,w;
            for(int i=1;i<=m;i++)
            {
                 scanf("%d%d%d",&u,&v,&w);
                 add(u,v,w);
                 add(v,u,w);
            }
            int st,en;
            scanf("%d%d",&st,&en);
            spfa(st);
            if(dis[en]==INF)//初始化为INF,那么如果终点距离还是INF,那么就说明没有找到最短路径
            {
                printf("Case %d : none!\n",cas);
                printf("\n");
                continue;
            }
            cnt=0;
            path[++cnt]=st;
            print(en);
            printf("Case %d : %d\n",cas,dis[en]);
            for(int i=1;i<=cnt;i++)
            {
                if(i<cnt) printf("%d ",path[i]);
                else printf("%d\n",path[i]);
            }
            printf("\n");
        }
        return 0;
    }

     

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值