并行算法学习之单源最短路径

来源:互联网 发布:贴吧查发帖记录软件 编辑:程序博客网 时间:2024/06/03 18:09

单源最短路径问题

是指从一个指定顶点s到其他所有顶点i之间的距离,因为是单一顶点到其他顶点的距离,所以称为单源
       设图G<V,E>是一个有向加权网络,其中VE分别为顶点集合和边集合,其边权邻接矩阵为W,边上权值w(i,j)>0,i,j∈VV={0,1,…,N-1}。
       设dist(i)为最短的路径长度,即距离,其中s∈V且i≠s。这里我是学习的Dijkstra算法,并将其并行化。

最短路径串行算法

       Dijkstra算法是单源最短路径问题的经典解法之一,还有很多单源最短路径的算法,比如Bellman-ford、spfa,下面说说Dijkstra算法的基本思想:
  假定有一个待搜索的顶点表VL,初始化时做:dist(s)<-0,dist(i)=∞(i≠s),VL=V。每次从VL(非空集)中选取这样的一个顶点u,它的dist(u)最小。将选出的u点作为搜索顶点,对于其他还在VL内的顶点v,若

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<math.h>using namespace std;const int maxn = 10000;int dist[maxn];int mp[maxn][maxn];bool vis[maxn];int n,m;const int oo = INT_MAX;void Dijkstra(int s){    for(int i=1; i<=n; i++)    {        dist[i] = mp[s][i];        vis[i]=false;    }    dist[s] = 0;    vis[s] = true;    int u;    for(int i=2; i<=n; i++)    {        int minn = oo;        for(int j=1; j<=n; j++)            if(!vis[j]&&minn>dist[j])            {                minn = dist[j];                u=j;            }        vis[u]=true;        for(int j=1; j<=n; j++)            if(!vis[j]&&mp[u][j]<oo)            {                if(dist[u]+mp[u][j]<dist[j])                    dist[j]=dist[u]+mp[u][j];            }    }}int main(){    for(int i=0; i<maxn; i++)        for(int j=0; j<maxn; j++)        {            if(i!=j)mp[i][j]=oo;            else mp[i][j]=0;        }    scanf("%d%d",&n,&m);    for(int i=0; i<m; i++)    {        int s,t,len;        scanf("%d%d%d",&s,&t,&len);        mp[s][t]=len;    }    int st;    scanf("%d",&st);    Dijkstra(st);    for(int i=1; i<=n; i++)        printf("%d ",dist[i]);    puts("");    return 0;}

以下这段代码我们可以进行并行化,每个处理器分派n = N/p(注意这里的n跟我程序中写的n不是一个n)个节点进行初始化

    for(int i=1; i<=n; i++)    {        dist[i] = mp[s][i];        vis[i]=false;    }    dist[s] = 0;

下面这段代码可以并行化为:首先每个处理器分派n个节点分别求局部最小值,然后再p个处理器合作求全局最小值,最后再将这一最小值广播出去。p个处理器合作方法如下:当p为偶数时,后p/2个处理器将自己的局部最小值分别发送到对应的前p/2个处理器中,由前p/2个处理器比较出2个局部最小值中相对较小者并保留。当p为奇数时,设p=2h+1,则后h个处理器的值分别发送到前h个处理器中,比较并保留当前最小值。一次这样的循环过后,p个最小值减少了一半,两次后变为1/4,如此一层一层的比较,logp次循环后,就可以得出唯一的全局最小值。

for(int j=1; j<=n; j++)            if(!vis[j]&&minn>dist[j])            {                minn = dist[j];                u=j;            }

下面的这段代码,可以每个处理器分配n个顶点,然后独立进行更新dist的操作。

        for(int j=1; j<=n; j++)            if(!vis[j]&&mp[u][j]<oo)            {                if(dist[u]+mp[u][j]<dist[j])                    dist[j]=dist[u]+mp[u][j];            }

根据以上思路,最短路径的并行算法就很明了了,使用了p个处理器,那么时间复杂度就是O(N^2/p+Nlogp)。
我们能够进行并行的方法就比较多了,可以用openmp或者mpi等等。最近在学习mpi并行编程,学的还不是很6,具体并行的程序就不贴啦。

0 0
原创粉丝点击