图论单源最短路问题(23_03_15)
题目都来源于luogu
dijkastra
本质是贪心,核心是dis[v] = min(dis[v],dis[u]+v),只能解决权值为正的情况
注意每次去查找那个离源点S最近的点时,可以通过优先队列的堆优化
P1144 最短路计数
#include <bits/stdc++.h>
using namespace std;
int n, m;
int cnt;
const int N = 1e3 + 5;
const int M = 1e5 + 5;
int head[N<<1];
struct Edge {
int to, next, val;
} edge[M << 1];
int dis[N << 1];
bool vis[N << 1];
void add_edge(int u, int v, int w) {
edge[++cnt].to = v;//注意这个建边写法是从1开始的
edge[cnt].next = head[u];
edge[cnt].val = w;
head[u] = cnt;
}
//一个我并不会写的堆优化
struct node {
int dis, pos;
bool operator < (const node &x)const {
return x.dis < dis;
}
};
priority_queue<node> pq;
void dij(int s) {
for (int i = 1; i <= n << 1; i++) {
dis[i] = 0x3ffffff;
}
memset(vis, 0, sizeof(vis));
dis[s] = 0;
pq.push({0, s});
while (!pq.empty()) {
node temp = pq.top();
pq.pop();
int x = temp.pos;
if (vis[x])
continue;
vis[x] = 1;
for (int i = head[x]; i; i = edge[i].next) {
int ux = edge[i].to;
if (dis[ux] > dis[x] + edge[i].val) {
dis[ux] = dis[x] + edge[i].val;
//cout << ux << " " << dis[ux] << endl;
if (!vis[ux]) {
pq.push({dis[ux], ux});
}
}
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
add_edge(a, b, c);
add_edge(b + n, a + n, c);
}
long long ans = 0 ;
dij(1);
for (int i = 1; i <= n; i++) {
ans += dis[i];
}
// cout << ans << endl;
dij(1 + n);
for (int i = 1 + n; i <= n << 1; i++) {
ans += dis[i];
}
cout << ans << endl;
return 0;
}
spfa
处理负环但是复杂度是O(NM)
实质是bfs
流程和dij差不多:1.取队首出队 2.遍历所有以队首为起点的边(x,i) 若dis[x] + w(x,i) < dis[i] ,更新dis[i]
3.如果i不在队列中,则入队 4.若队列为空,则跳出循环
//spfa求最短路板子
#include <bits/stdc++.h>
using namespace std;
int n, m;
int cnt;
const int N = 1e4 + 5;
const int M = 5e5 + 5;
const long long oo = (1 << 31) - 1;
int head[N];
struct Edge {
int to, next, val;
} edge[M << 1];
long long dis[N];
bool inq[N];
void add_edge(int u, int v, int w) {
edge[++cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].val = w;
head[u] = cnt;
}
queue<int> q;
void spfa(int s) {
for (int i = 1; i <= n ; i++) {
dis[i] = oo;
}
memset(inq, 0, sizeof(inq));
dis[s] = 0;
q.push(s);
inq[s] = 1;
while (!q.empty()) {
int x = q.front();
q.pop();
inq[x] = 0;
for (int i = head[x]; i; i = edge[i].next) {
int ux = edge[i].to;
if (dis[ux] > dis[x] + edge[i].val) {
dis[ux] = dis[x] + edge[i].val;
if (!inq[ux]) {
q.push(ux);
inq[ux] = 1;
}
}
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int s;
cin >> n >> m >> s;
for (int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
add_edge(a, b, c);
}
long long ans = 0 ;
spfa(s);
for (int i = 1; i < n; i++) {
cout << dis[i] << " ";
}
cout << dis[n] << endl;
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库