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

单源最短路径问题

是指从一个指定顶点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,具体并行的程序就不贴啦。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值