现在的位置: 首页 > 算法 > 正文

poj 1847 Tram (SPFA最短路)

2018年09月22日 算法 ⁄ 共 1366字 ⁄ 字号 评论关闭

题目链接:   http://poj.org/problem?id=1847

题目大意:  这道题理解起来有点恶心

                 有N个铁轨交叉口,这些交叉口与其他交叉口通过铁轨连接

                 电车开进一个交叉口,想去另一个交叉口,必须要把灯照向下一个交叉口

                 求从A到B驾驶员需要转换灯的最小次数

解题思路:  这道题关键在于构图,每一个交叉点连接的第一条边为0

                 其他的边为1,求A到B的最短路径

       感想: 本来想找一道Dijkstra的题,试验最小二叉堆优化之后的效率

                 理解了题目发现顶点最大才100,堆的效率很难体现出来

                 而且这道题用SPFA更加方便,开始WA了几次

                 原来是入队时判断错了,写过这么多的SPFA,真不应该

                 SPFA的思想每走一个点,修改到这个点的当前最优解,下次再准备走这点

                 时判断这次的解是不是比上一次还优?是则入队,即使到达终点也不用停止,最

                 优解总会有界限,所以当队列为空的时候,就是最优解!

代码:

//SPFA最短路模版
//入队的时候需要注意不要判断错了!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 101
#define INF 0x3f3f3f3f
int n,m,visit[MAX],list[MAX*MAX],near[MAX],edge[MAX][MAX];

int SPFA(int A,int B)
{
    int e,s,i,v0;
    e=s=0;
    list[s++]=A;    //初始化
    visit[A]=1;
    near[A]=0;
    while(s!=e)
    {
        v0=list[e++];
        visit[v0]=0;
        for(i=1;i<=n;i++)
        {
            if(edge[v0][i]<INF&&near[v0]+edge[v0][i]<near[i])
            {
               if(!visit[i])                   //**这里最容易错误了**
               {
                    list[s++]=i;
                    visit[i]=1;
               }
                near[i]=near[v0]+edge[v0][i];  //即使队列里面有,也要改变它的值
            }
        }
    }
    return near[B];
}

int main()
{
    int i,j,k,A,B,to;
    while(scanf("%d%d%d",&n,&A,&B)!=EOF)
    {
        memset(edge,INF,sizeof(edge));
        memset(near,INF,sizeof(near));
        memset(visit,0,sizeof(visit));
        for(i=1;i<=n;i++)            //构图过程
        {
            scanf("%d",&m);
            for(j=1;j<=m;j++)
            {
                scanf("%d",&to);
                if(j==1)
                    edge[i][to]=0;   //第一条边为0
                else
                    edge[i][to]=1;   //其余的边为1
            }
        }
        if(A==B)     //终点和起点一样,直接输出
        {
            printf("0\n");
            return 0;
        }
        k=SPFA(A,B);
        if(k==INF)   //不可到达B点
            printf("-1\n");
        else
            printf("%d\n",k);
    }
    return 0;
}

注:原创文章,转载求注明出处

抱歉!评论已关闭.