无优先队列优化且用邻接矩阵存储图,这题如用邻接矩阵存储图会爆内存。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int p = 10005;
int a[p][p];//存放点与点的距离
int dist[p];//源点到各个点的最短距离
int pre[p];//计算过的点
int vis[p];//判断是否已经加入pre,是否已访问
int n, m;
int st; //源节点
void Dijkstra(int v)
{
int i, j;
for (i = 0; i < n; ++i)
{
if (i != v)
{
dist[i] = a[v][i];
}
vis[i] = false;
}
vis[v] = true;
dist[v] = 0;
pre[0] = v;
//对各个数组进行初始化
for (i = 0; i < n; ++i)
{
int minset = inf;
int u = v;
for (j = 0; j < n; ++j)
{
if (!vis[j] && dist[j] < minset)
//找到剩余节点中最小的节点
{
u = j;
minset = dist[u];
}
}
vis[u] = true; //u代表当前未加入数组且数值最小的点
//将节点标记为以访问,相当于加入s数组中
for (j = 0; j < n; ++j)
{
if (!vis[j] && a[u][j] < inf)
//a[u][j] < MAXN指更新u的可达点
{
if (dist[u] + a[u][j] < dist[j])
{
dist[j] = dist[u] + a[u][j];
pre[j] = u;
//储存得出最短路径的前一个节点,用于路径还原
}
}
}
}
}
int main()
{
scanf("%d%d%d", &n, &m, &st);
memset(a, 0x3f, sizeof(a));
memset(dist, 0x3f, sizeof(dist));
int i, j;
for (i = 0; i < m; ++i)
{
int x, y, d;
scanf("%d %d %d", &x, &y, &d);
a[x - 1][y - 1] = min(a[x - 1][y - 1],d);
}
//int v;
//scanf("%d",&v);
Dijkstra(st-1); //数组里是从0到n-1,所以传入st-1
for (int i = 0; i < n; ++i) //输出V0到各点的最小路径长度
{
if(i)
printf(" ");
if(dist[i]!=inf)
printf("%d", dist[i]);
else
printf("2147483647");
}
// int k=n-1; //输出V0到vn-1的前驱,即路径
// while(pre[k]!=k){
// cout<<pre[k]<<" ";
// k=pre[k];
// }
/*for(int i = 0;i < n;++i)
{
printf("%d ",s[i]);
}
printf("\n");
for(int i = 0;i < n;++i)
{
printf("%d ",pre[i]);
}
printf("\n");*/
return 0;
}
以邻接表存储,优先队列优化:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 10005;
int dist[maxn];//源点到各个点的最短距离
int pre[maxn];//计算过的点
int vis[maxn];//判断是否已经加入pre,是否已访问
int n, m;
int st; //源节点
struct Edge {
int u; int d;
Edge(int uu, int dd) {
u = uu;
d = dd;
}
bool operator<(const Edge& e) const //注意这个const必须要加上,不然编译错误
{
return d > e.d; //小顶堆,大顶堆将>改为<
}
};
vector<Edge>g[maxn];
void Dijkstra(int v)
{
priority_queue<Edge>q;
memset(pre, -1, sizeof(pre));
memset(dist, 0x3f, sizeof(dist));
dist[v] = 0;
q.push(Edge(v, 0));
while (!q.empty()) {
Edge e1 = q.top();
q.pop();
int u = e1.u; //顶点编号
if (vis[u]) //说明dist[u]已经是当前最短,这句话很关键!可以大幅度减少不必要的操作
continue;
vis[u]=1;
for (int i = 0; i < g[u].size(); i++) {
Edge e2 = g[u][i];
if (dist[e2.u] > dist[u] + e2.d) {
dist[e2.u] = dist[u] + e2.d;
//pre[e2.u] = u; //记录e2.u的前驱,用于保存路径
q.push(Edge(e2.u, dist[e2.u]));
}
}
}
}
int main()
{
scanf("%d%d%d", &n, &m, &st);
for (int i = 0; i < m; ++i)
{
int x, y, d;
scanf("%d %d %d", &x, &y, &d);
g[x - 1].push_back(Edge(y-1,d)); //规定序号从0到n-1
}
Dijkstra(st-1); //图里是从0到n-1,所以传入st-1
for (int i = 0; i < n; ++i) //输出V0到各点的最小路径长度
{
if(i)
printf(" ");
if(dist[i]!=inf)
printf("%d", dist[i]);
else
printf("2147483647");
}
//int k=n-1; //输出V0到vn-1的前驱,即路径
//while(pre[k]!=-1){
// cout<<pre[k]<<" ";
// k=pre[k];
//}
return 0;
}