Dijkstra
Dijkstra算法流程
1.初始化 dist[1]=0,其余节点的
d
i
s
t
dist
dist 值为正无穷大。
2.找出未标记的、
d
i
s
t
[
x
]
dist[ x ]
dist[x]最小的节点
x
x
x ,然后标记节点
x
x
x。
3.扫描节点
x
x
x的所有出边
(
x
,
y
,
z
)
(x,y,z)
(x,y,z),若
d
i
s
t
[
y
]
dist[ y ]
dist[y] >
d
i
s
t
[
x
]
dist[ x ]
dist[x] +
z
z
z,则
d
i
s
t
[
y
]
dist[ y ]
dist[y] =
d
i
s
t
[
x
]
dist[ x ]
dist[x] +
z
z
z
4.重复上述 2~3 两个步骤,直到所有的节点都被标记 。
迪杰斯特拉算法不能处理存在负权的图,当权值是非负时,全局最小值不可能再被其他节点更新,所以在第
1
1
1 步选出的节点
x
x
x 肯定满足:
d
i
s
t
[
x
]
dist[ x ]
dist[x] 已经是起点到
x
x
x 的最短路径。不断选择全局最小值进行标记和扩展,最终可得到起点 1 到每个节点的最短路径的长度。
邻接表
加入有向边 ( u , v ) (u,v) (u,v),权值为 k k k
void Add(int u,int v,int k)
{
edge[++tot].val=k;
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot;
}
访问从 u 出发的所有边
for(int i=head[u];i;i=edge[i].next) // -1取反是 0
{
int v=edge[i].to;
int val=edge[i].val;
if(dist[v]>dist[u]+val) //更新最短路径
{
dist[v]=dist[u]+val;
pre[v]=u;
p.push(PII(dist[v],v));
}
}
Dijkstra
题目大意
You are given a weighted undirected graph. The vertices are enumerated from 1 to n. Your task is to find the shortest path between the vertex 1 and the vertex n.
Input
The first line contains two integers n and m (2 ≤
n
n
n ≤
1
0
5
10^5
105, 0 ≤
m
m
m ≤
1
0
5
10^5
105), where
n
n
n is the number of vertices and
m
m
m is the number of edges. Following
m
m
m lines contain one edge each in form
a
i
a_i
ai,
b
i
b_i
bi and
w
i
w_i
wi (1 ≤
a
i
a_i
ai,
b
i
b_i
bi ≤ n, 1 ≤
w
i
w_i
wi ≤
1
0
6
10^6
106), where
a
i
a_i
ai,
b
i
b_i
bi are edge endpoints and
w
i
w_i
wi is the length of the edge.
It is possible that the graph has loops and multiple edges between pair of vertices.
Output
Write the only integer -1 in case of no path. Write the shortest path in opposite case. If there are many solutions, print any of them.
输入样例
5 6
1 2 2
2 5 5
2 3 4
1 4 1
4 3 3
3 5 1
输出样例
1 4 3 5
题解
给你一个无向图,给你
n
n
n 个点,
m
m
m条边,询问从1~
n
n
n是否存在单源最短路径,如果存在,请输出路径,如果不存在,请输出-1
无向图空间开两倍,爆
l
o
n
g
long
long
l
o
n
g
long
long,
0
x
3
f
3
f
3
f
3
f
0x3f3f3f3f
0x3f3f3f3f 是
i
n
t
int
int类型的最大值,所以这里的无穷大应该取
1
e
18
1e^{18}
1e18多一点,开个
p
r
e
[
]
pre[]
pre[] 数组记录最短路径的走向,最后看是否存在单源最短路径,如果存在,输出
p
r
e
[
]
pre[]
pre[] 数组的内容,如果不存在,就输出 -
1
1
1
#include <bits/stdc++.h>
#define pb push_back
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e5 + 20;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
typedef pair<int,int> PII;
int n,m;
int tot;
int head[maxn];
struct Node{
int to;
ll val;
int next;
}edge[maxn<<1];
ll dist[maxn];
bool vis[maxn];
int pre[maxn];
int ans[maxn];
void Add(int u,int v,int k)
{
edge[++tot].val=k;
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot;
}
void Dijkstra(int s)
{
for(int i=1;i<=n;++i) dist[i]=INF;
memset(vis,0,sizeof(vis));
dist[s]=0;
priority_queue<PII,vector<PII>,greater<PII> > p;
p.push(pair<int,int>(0,s));
while(p.size())
{
PII temp=p.top();
p.pop();
int u=temp.second;
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
int val=edge[i].val;
if(dist[v]>dist[u]+val)
{
dist[v]=dist[u]+val;
pre[v]=u;
p.push(PII(dist[v],v));
}
}
}
}
int main()
{
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
Add(x,y,z);
Add(y,x,z);
}
Dijkstra(1);
if(dist[n]==INF) printf("-1\n");
else
{
int t=n,idx=0;
while(t!=1)
{
ans[++idx]=t;
t=pre[t];
}
ans[++idx]=1;
for(int i=idx;i;i--) printf("%d ",ans[i]);
}
return 0;
}