两种写法
第一种:时间复杂度:O(n2)点的数量,未使用优先队列优化
/*
时间复杂度:O(n2)点的数量
*/
#include<bits/stdc++.h>
using namespace std;
#define MAX 10000
#define inf 2147483647
//0x3f3f3f3f
long long int d[MAX];//结点i的路径长度为d[i]
long long int v[MAX];//标记是否使用过该点
long long int w[MAX][MAX];//记录两点之间的花费
long long int start=0,n,m;//起始点begin 点n表示点的数量 m表示边的数量
long long int fa[MAX];//维护父亲结点,用来找路径
void init()//初始化
{
for(int i=1;i<=n;i++)//把起点之外的点的距离设为inf,起点的距离设为0
{
d[i]=(i==start ? 0:inf);
}
memset(v,0,sizeof(v));//全部为未使用 0:未使用 1:使用
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
w[i][j]=inf;
}
void Dijkstra()
{
for(int i=1;i<=n;i++)
{
int pos,Min=inf;
for(int j=1;j<=n;j++)//未标记的结点中,结点d[j]值最小的点 pos
{
if(!v[j]&&d[j]<=Min)
{
Min=d[j];
pos=j;
}
}
v[pos]=1;//标记最小结点 pos
for(int j=1;j<=n;j++)//对于从pos出发的所有边(pos,j),更新 d[j]=min(d[j],d[pos]+w[pos][j])
{
//d[j]=min(d[j],d[pos]+w[pos][j]);
if(d[j]>d[pos]+w[pos][j])
{
d[j]=d[pos]+w[pos][j];
fa[j]=pos;
}
}
}
}
void findway(int k)
{
long long int value=d[k];
int z=k;
while(value!=0)
{
for(int i=1;i<=n;i++)
{
if(d[z]==d[i]+w[i][z])
{
value-=w[i][z];
z=i;
cout<<z<<endl;
break;
}
}
}
}
int main()
{
cin>>n>>m>>start;
init();
for(int i=0;i<m;i++)
{
long long int a,b,c;
cin>>a>>b>>c;
//无向图
if(w[a][b]>c)
w[a][b]=c;
//w[b][a]=c;
}
Dijkstra();
for(int i=1;i<=n;i++)
{
if(i==1)
printf("%lld",d[i]);
else
printf(" %lld",d[i]);
}
cout<<endl;
//findway(5);
for(int i=1; i<=n; i++)
{
if(i!=start)
{
cout<<i;
int p=i;
while(fa[p]!=0)
{
cout<<"-->"<<fa[p];
p=fa[p];
}
cout<<endl;
}
}
return 0;
}
/*
输入:
5 7 1
1 2 10
1 4 25
1 5 80
2 3 40
3 5 10
4 3 20
4 5 50
输出:
0 10 45 25 55
2-->1
3-->4-->1
4-->1
5-->3-->4-->1
*/
第二种:时间复杂度:O(mlogn)点的数量,使用优先队列优化
/*
时间复杂度:O(mlogn)点的数量
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005 //最大值为结点的个数
#define INF 2147483647
typedef long long int ll;
vector<ll> G[maxn]; //当点的数量过大时,这里有可能会内存溢出,开全局变量就行
struct Dijkstra
{
struct Edge
{
ll from, to, dist;
Edge(int u, int v, int d) :from(u), to(v), dist(d) {}
};
ll n, m,k; //n个点,m个边
vector<Edge> edges;
bool done[maxn]; //是否已永久标号
ll d[maxn]; //s到各个点的距离
ll p[maxn]; //最短路中的上一条弧
void init(ll n) //初始化边和点
{
this->n = n;
for (int i = 0; i < n; i++) G[i].clear(),p[i]=0;
edges.clear();
}
void AddEdge(ll from, ll to, ll dist) //添加边
{
edges.push_back(Edge(from, to, dist));
k = edges.size();
G[from].push_back(k - 1);
}
struct HeapNode //寻找未使用的最小d[i],把的d[i]和i绑定到一起
{
ll d, u;
bool operator < (const HeapNode& rhs) const
{
return d > rhs.d;
}
};
void dijkstra(int s)
{
priority_queue<HeapNode> Q;
for (int i = 0; i < n; i++) d[i] = INF;
d[s] = 0;
memset(done, 0, sizeof(done));
Q.push((HeapNode) { 0, s });
while (!Q.empty())
{
HeapNode x = Q.top(); Q.pop();
ll u = x.u;
if (done[u]) continue;
done[u] = true;
ll glen= G[u].size();
for (int i = 0; i < glen; i++)
{
Edge& e = edges[G[u][i]];
if (d[e.to] > d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
p[e.to] = u;
Q.push((HeapNode) { d[e.to], e.to });
}
}
}
}
};
int main()
{
Dijkstra a;
ll n,m,start;
cin>>n>>m>>start;
a.n=n+1; //模板从0到n-1,如果需要从1到n,则需要加 1
a.m=m;
a.init(a.n);
for(int i=0;i<a.m;i++)
{
ll from,to,dist;
cin>>from>>to>>dist;
a.AddEdge(from,to,dist);
}
a.dijkstra(start);
for(int i=1;i<a.n;i++)
{
if(i==1)
cout<<a.d[i];
else
cout<<' '<<a.d[i];
}
cout<<endl;
for(int i=1; i<a.n; i++)
{
if(i!=start)
{
cout<<i;
ll d=i;
while(a.p[d]!=0)
{
cout<<"-->"<<a.p[d];
d=a.p[d];
}
cout<<endl;
}
}
return 0;
}
/*
洛谷 P3371
洛谷 P4779
输入:
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出:
0 2 4 3
2-->1
3-->2-->1
4-->2-->1
*/