本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-02-16 15:51:09
最短路问题—— Dijkstra
虽然并不是完全掌握
例题:
Dijkstra 的条件:
- 用于求最短路问题
- 确定起点
思想
运用贪心的思想,在当前起点的出边中找到 未被遍历 过的边权最小的点,将其标记并更新最短路径,直到遍历到终点。
实现:
- 邻接矩阵
时间复杂度 $O(n^2)$。
\/\/map是邻接矩阵数组,map[i][i] = 0,若i,j之间没有边则map[i][j] = INF
void Djikstra(int x){\/\/x是起点
memset(d,INF,siziof(d));\/\/求最短,初始化为较大数
d[x] = 0;\/\/到他本身
for(int i = 1;i <= n;i++){
int j = 0;\/\/当前最小
for(int k = 1;k <= n;k++){\/\/找最小的未被访问的d[j]
if(!vis[k] && d[k] <= d[j]){
j=k;
}
}
vis[j] = 1;
for(int k = 1;k <= n;k++){\/\/更新d[j]
d[k] = min(d[k],d[j] + map[j][k]);
}
}
}
- 邻接表
时间复杂度 $O(n^2)$。
\/\/head是表头,ver是当前边的指向的点,nxt是下一条边,data是权值
void Djikstra(int x){\/\/x是起点
memset(d,INF,siziof(d));\/\/求最短,初始化为较大数
d[x] = 0;\/\/到他本身
for(int i = 1;i <= n;i++){
int j = 0;\/\/当前最小
for(int k = 1;k <= n;k++){\/\/找最小的未被访问的d[j]
if(!vis[k] && d[k] <= d[j]){
j=k;
}
}
vis[j] = 1;
for(int k = head[j];k != -1;k = nxt[k]){\/\/更新d[j]
d[ver[k]] = min(d[ver[k],d[j]]+data[k]);
}
}
}
堆(优先队列)优化
优化条件
- 边权非负
- 边数远小于$n^2$,即$cnt(edge) \le 2\cdot10^5$
vector做法
时间复杂度 $O(m\cdot log_2m)$
struct node{
int d;\/\/d是当前的最短路径
int u;\/\/u是起点
bool operator < (const node & rhs) const {
return d > rhs.d;
}\/\/重载运算符
};
vector <int> e[N];\/\/e[i][]表示第i个点所连的所有边
vector <int> w[N];\/\/w[i][]表示e[i][]所连边的权值
void Dijkstra(){
priority_queue <node> q;
F(2,i,n) d[i]=INF;
node tn;
tn.d=0,tn.u=1;
q.push(tn);
int u;
\/\/初始化
while(!q.empty()){
node t=q.top();
q.pop();
u=t.u;
if(vis[u]) continue;\/\/要求未被标记
vis[u]=1;
for(int i = 0;i < e[u].size();i++){\/\/vector默认从0开始,遍历从u到达的边
int v = e[u][i];\/\/v是终点
if(d[v] > d[u] + w[u][i]){\/\/这条路径的长度小于当前最短路径
d[v] = d[u] + w[u][i];\/\/更新最短路径
pre[v]=u;\/\/记忆路径
tn.d=d[v],tn.u=v;
q.push(tn);\/\/作为新起点入堆
}
}
}
}
萌新第一次写博客

鲁ICP备2025150228号