LuoGu例题
我参考了这篇博文
首先介绍普通的dijkstra算法
dijkstra用于求单源最短路,但不支持负权
dijkstra算法的过程中把点分成两类,定义蓝点为已确定最短路的点,白点为未确定最短路的点
操作为下:
显然,dijkstra的时间复杂度为O(n^2)
发现2操作可以用堆优化到log级别
用小根堆维护dis值,每次取出堆中第一个,若没标记则进行后面的步骤
Code:
var
heap:array[0..1000000] of record
num,dis:longint;
end;
edge:array[0..1000000] of record
t,next,dis:longint;
end;
head,dis:array[0..1000000] of longint;
vis:array[0..1000000] of boolean;
n,m,s,x,y,z,i,e,len,num:longint;
procedure add(x,y,z:longint);
begin
inc(num);
edge[i].t := y;
edge[i].dis := z;
edge[i].next := head[x];
head[x] := num;
end;
procedure swap(var x,y:longint);
var
tmp:longint;
begin
tmp := x; x := y; y := tmp;
end;
procedure push(x,y:longint);
var
i:longint;
begin
inc(len);
heap[len].num := x; heap[len].dis := y;
i := len;
while i > 1 do
begin
if heap[i].dis < heap[i >> 1].dis then
begin
swap(heap[i].num,heap[i >> 1].num);
swap(heap[i].dis,heap[i >> 1].dis);
i := i >> 1;
end else break;
end;
end;
procedure pop;
var
i,x:longint;
begin
heap[1].num := heap[len].num;
heap[1].dis := heap[len].dis;
dec(len);
i := 1;
while (i << 1) <= len do
begin
if ((i << 1 or 1) > len) or (heap[i << 1].dis < heap[i << 1 or 1].dis) then
x := i << 1 else x := i << 1 or 1;
if heap[i].dis > heap[x].dis then
begin
swap(heap[i].num,heap[x].num);
swap(heap[i].dis,heap[x].dis);
i := x;
end else break;
end;
end;
begin
readln(n,m,s);
for i := 1 to m do
begin
readln(x,y,z);
add(x,y,z);
end;
for i := 1 to n do dis[i] := maxlongint;
dis[s] := 0;
len := 1;
heap[1].num := s;
heap[1].dis := 0;
while len > 0 do
begin
x := heap[1].num;
y := heap[1].dis;
pop;
if vis[x] then continue;
vis[x] := true;
i := head[x];
while i <> 0 do
begin
e := edge[i].t;
if dis[e] > y + edge[i].dis then
begin
dis[e] := y + edge[i].dis;
push(e,dis[e]);
end;
i := edge[i].next;
end;
end;
for i := 1 to n do write(dis[i],' ');
end.
pascal转c++,完成c++版的dijkstra
Code:
/*
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
*/
#include
#define res register int
#define ll long long
#define maxn 2 * 200010
using namespace std;
struct node {
int u, len;
bool operator < (const node &x) const {
return x.len < len;
}
};
struct Edge {
int to, next, len;
} edge[maxn];
int n, m, s, head[maxn], dis[maxn], vis[maxn], num;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) w |= c == '-';
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
inline void add_edge(int x, int y, int z) { edge[++ num].to = y; edge[num].next = head[x]; edge[num].len = z; head[x] = num; }
int main() {
//input
n = read(), m = read(), s = read();
for (res i = 1; i <= m; ++ i) {
int x = read(), y = read(), z = read();
add_edge(x, y, z);
}
//dijkstra
memset(dis, 0x3f, sizeof(dis)); dis[s] = 0;
priority_queue <node> q;
q.push( (node) { s, 0 });
while (!q.empty()) {
node tmp = q.top(); q.pop();
int u = tmp.u, len = tmp.len;
if (vis[u]) continue;
vis[u] = 1;
for (res i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (dis[v] > len + edge[i].len){
dis[v] = len + edge[i].len;
q.push( (node) { v, dis[v] });
}
}
}
//output
for (res i = 1; i <= n; ++ i) printf("%d ", dis[i]);
return 0;
}