您的位置:首页 > 其它

单源最短路-SPFA(poj2387)

2015-11-25 17:58 232 查看
题目链接: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
<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: