图论单源最短路问题(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;
}

posted @   oddpointa  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示