您的位置:首页 > 其它

SPFA的两种实现形式(二维数组与数组模拟邻接表)

2015-07-21 16:56 447 查看
【输入描述】

第一行有两个数n,m表示有n个点m条边

第2~m+1行有三个数a,b,c表示a点与b点间的距离

第m+2行有两个数x,y表示询问x点到y点的最短路

【输出描述】

一个数ans,表示x点到y点的最短路长度

【样例输入】

5 7

1 3 7

2 4 6

1 2 2

2 5 3

1 4 8

3 5 1

5 4 6

1 3

样例输出

6

如图所示:



1.二维数组实现

#include<algorithm>

#include<iostream>

#include<cstring>

#include<cstdio>

#include<queue>

using namespace std;

const int INF = 1000;

int n,m,x,y,dist[INF]; //x,y分别为起点和终点,n,m分别为点数与边数,dist存放结果;

int dis[INF][INF],w[INF][INF]; //dis用来存储边权;w[i,0]存储与i有关联的点的个数;w[i,j]存储与i关联的各个点

bool used[INF]; //用来判断是否在队列中

int main()

{

memset(dist,127/3,sizeof(dist));

memset(used,false,sizeof(used));

memset(dis,127/3,sizeof(dis));

scanf("%d %d", &n, &m);

int a,b,c;

for ( int i = 1 ; i <= m ; i++ )

{

scanf("%d %d %d", &a, &b, &c);

w[a][0]++ ; w[a][w[a][0]] = b ; dis[a] = c ;

w[b][0]++ ; w[b][w[b][0]] = a ; dis[b][a] = c ;

}

scanf("%d %d", &x, &y);

queue<int> p;

dist[x] = 0;

p.push(x);used[x] = true;

while (!p.empty())

{

int now = p.front();

for ( int i = 1 ; i <= w[now][0] ; i ++ )

{

//逐点松弛,如果不在队列中则加入队列

if ( dist[w[now][i]] > dist[now] + dis[now][w[now][i]] )

{

dist[w[now][i]] = dist[now] + dis[now][w[now][i]];

if ( !used[w[now][i]] )

{

p.push(w[now][i]);

used[w[now][i]] = true;

}

}

}

p.pop();

used[now] = false;

}

printf("%d", dist[y]);

return 0;

}

2.[b]数组模拟邻接表实现//表现为存储空间上的优越性


#include<algorithm>

#include<iostream>

#include<cstring>

#include<cstdio>

#include<queue>

using namespace std;

const int INF = 1000001;

const int end = -1;

int f[INF],dist[INF],n,m,x,y,a,b,c,d = 0;//假设最多不超过INF个点

bool used[INF];

struct q{

int ans,next,link;

}s[INF];//假设最多不超过INF条边

void add(int a, int b, int c)

{

//用s.link存储该点指向的一个点

//s.ans存储边长

/*s.next存储上一个该点指向的点在数组s中的位置(在下面的松弛过程中如果结果是-1,就说明该点所连接的点已经全部松弛过了)*/

d++;

s[d].ans = c;

s[d].link = b;

s[d].next = f[a];

f[a] = d; //记录这一路线(两点加一边)在数组s中的位置

}

int spfa(int a,int b)

{

//原理同二维数组写法的原理,只是把w数组的作用用邻接表代替了

queue<int> p;

memset(dist,127,sizeof(dist));

dist[a] = 0 ;

p.push(a);used[a] = true;

while(!p.empty())

{

int now = p.front();

for (int i = f[now] ; i != -1 ; i = s[i].next )

//根据链逐点松弛,作用同二维数组写法里的w数组

{

if ( dist[s[i].link] > s[i].ans+dist[now] )

{

dist[s[i].link] = s[i].ans+dist[now];

if (!used[s[i].link])

{

p.push(s[i].link);

used[s[i].link] = true;

}

}

}

p.pop();

used[now] = false;

}

return dist[b];

}

int main()

{

scanf("%d %d", &n, &m);

memset(f,end,sizeof(f));

memset(used,false,sizeof(used));

for (int i = 1 ; i <= m ; i++)

{

scanf("%d %d %d\n", &a , &b, &c);

add(a,b,c);

add(b,a,c);

}

scanf("%d %d", &x, &y);

int ans = spfa(x,y);

printf("%d", ans);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: