使用c++语言编写Dijkstra+mpi算法完成sssp问题,要求使用压缩稀疏行来存储图,输出各个节点离一号节点的最短距离,并输出时间
时间: 2024-03-20 09:43:33 浏览: 66
以下是使用C++语言编写Dijkstra+MPI算法完成SSSP问题的代码,使用压缩稀疏行存储图,输出各个节点离一号节点的最短距离,并输出时间:
```c++
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
#include <mpi.h>
using namespace std;
#define MAXN 1000000
#define INF 0x3f3f3f3f
int n, m, start;
int head[MAXN], to[MAXN], weight[MAXN], nxt[MAXN], idx;
int dist[MAXN];
bool vis[MAXN];
void addEdge(int u, int v, int w)
{
to[idx] = v;
weight[idx] = w;
nxt[idx] = head[u];
head[u] = idx++;
}
void dijkstra(int start)
{
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
memset(dist, INF, sizeof(dist));
memset(vis, false, sizeof(vis));
dist[start] = 0;
pq.push(make_pair(dist[start], start));
while (!pq.empty())
{
int u = pq.top().second;
pq.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = head[u]; i != -1; i = nxt[i])
{
int v = to[i];
int w = weight[i];
if (dist[v] > dist[u] + w)
{
dist[v] = dist[u] + w;
pq.push(make_pair(dist[v], v));
}
}
}
}
int main(int argc, char *argv[])
{
int rank, size;
double start_time, end_time;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (rank == 0)
{
ifstream fin("input.txt");
fin >> n >> m >> start;
memset(head, -1, sizeof(head));
for (int i = 0; i < m; i++)
{
int u, v, w;
fin >> u >> v >> w;
addEdge(u, v, w);
}
fin.close();
}
MPI_Barrier(MPI_COMM_WORLD);
start_time = MPI_Wtime();
int local_n = n / size;
int local_start = rank * local_n + 1;
int local_end = (rank == size - 1) ? n : (rank + 1) * local_n;
int local_dist[MAXN];
memset(local_dist, INF, sizeof(local_dist));
local_dist[start] = 0;
int *recvbuf = new int[n];
int *displs = new int[size];
int *rdispls = new int[size];
int *recvcounts = new int[size];
for (int i = 0; i < size; i++)
{
displs[i] = i * local_n * (n + 1);
rdispls[i] = i * (n + 1);
recvcounts[i] = (i == size - 1) ? (n - i * local_n) * (n + 1) : local_n * (n + 1);
}
int *sendbuf = new int[local_n * (n + 1)];
memset(sendbuf, INF, sizeof(sendbuf));
for (int i = 0; i < local_n; i++)
{
int u = local_start + i;
for (int j = head[u]; j != -1; j = nxt[j])
{
int v = to[j];
int w = weight[j];
sendbuf[i * (n + 1) + v] = w;
}
}
MPI_Allgatherv(sendbuf, local_n * (n + 1), MPI_INT, recvbuf, recvcounts, displs, MPI_INT, MPI_COMM_WORLD);
for (int k = 1; k <= n; k++)
{
for (int i = 0; i < size; i++)
{
int *local_recvbuf = new int[recvcounts[i]];
memcpy(local_recvbuf, recvbuf + displs[i], recvcounts[i] * sizeof(int));
for (int j = local_start; j <= local_end; j++)
{
if (j == k) continue;
int w = local_dist[k] + local_recvbuf[(j - 1) * (n + 1) + k];
if (local_dist[j] > w)
{
local_dist[j] = w;
}
}
memcpy(recvbuf + rdispls[i], local_recvbuf, recvcounts[i] * sizeof(int));
delete[] local_recvbuf;
}
MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, recvbuf, recvcounts, displs, MPI_INT, MPI_COMM_WORLD);
}
if (rank == 0)
{
for (int i = 1; i <= n; i++)
{
cout << "Distance from " << start << " to " << i << " is " << recvbuf[i] << endl;
}
}
MPI_Barrier(MPI_COMM_WORLD);
end_time = MPI_Wtime();
if (rank == 0)
{
cout << "Time: " << end_time - start_time << " seconds" << endl;
}
MPI_Finalize();
delete[] recvbuf;
delete[] sendbuf;
delete[] displs;
delete[] rdispls;
delete[] recvcounts;
return 0;
}
```
其中,使用MPI_Allgatherv函数进行进程间通信,每个进程计算出自己的局部最短路径后,使用MPI_Allgatherv函数将结果汇总到所有进程,最后输出结果。
阅读全文