单源最短路-SPFA(poj2387)

来源:互联网 发布:php和java哪个好找工作 编辑:程序博客网 时间:2024/05/01 01:45

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

1.用邻接表存图
用u[i],v[i],w[i]数组表示第i条边是从点u[i]到v[i],路径长度是w[i];
用first[i]数组存顶点i的第一条边的编号;
用next[i]数组存第i条边的下一条边的编号;
2.用dis[i]数组表示从源点到i点的最短路径;
3.用book[i]数组标记点i是否在队列中;

SPFA算法步骤:
1.初始时将源点加入队列
2.每次从队首取出一个顶点,对这个顶点的所有出边进行松弛操作,若松弛成功,这个出边指向的顶点入队,对当前顶点处理完后出队
3.重复第2步直到队列为空

算法复杂度:最坏O(N*M)

#include <iostream>using namespace std;int u[4005],v[4005],w[4005]; //邻接表存图int first[1005];  //点i的第一条边的编号int ne[4005]; // 边i的下一条边int dis[1005],book[1005];int que[9999999],head = 1,tail = 1; //定义队列并初始化int inf = 99999999;int main(){    int t,n;    cin>>t>>n;    // 初始化dis数组 ,表示1号顶点到其余各个顶点的路程    for (int i =1; i <= n; i++)        dis[i] = inf;    dis[1] = 0;    //初始化book数组,一开始所有顶点都不在队列中    for (int i =1; i<= n; i++)        book[i] = 0;    //初始化first数组,next数组,表示顶点暂时都没有边    for(int i =1;i <= n;i++)    {        first[i] = -1;    }    //读入边,建立邻接表    for (int i =1; i <= 2*t; i++)    {        cin>>u[i]>>v[i]>>w[i];        ne[i] = first[u[i]];        first[u[i]] = i;        i++;        u[i] = v[i - 1];        v[i] = u[i - 1];        w[i] = w[i - 1];        ne[i] = first[u[i]];        first[u[i]] = i;    }    //1号顶点入队    que[tail] = 1;    tail++;    book[1] = 1;    while (head<tail)   //队列不为空时循环    {        int k = first[que[head]];        while (k != -1)        {            if (dis[v[k]] > dis[u[k]] + w[k])            {                dis[v[k]] = dis[u[k]] + w[k];                if (book[v[k]] == 0 )                {                    que[tail] = v[k];                    tail++;                    book[v[k]] = 1;                }            }            k = ne[k];        }        book[que[head]] = 0;        head++;    }    cout<<dis[n]<<endl;    return 0;}
0 0
原创粉丝点击