P1001 A+B Problem(整活-dijstra堆最佳化)

hymcr05發表於2024-08-15

OK 啊,這就是普通的 \(a+b\)
這是一道十分淼的題目,乍一看,這不就是dijstra堆最佳化的模板題嗎?
首先,建立三個節點,兩條線
行,OK 開始 Code

#include <bits/stdc++.h>
using namespace std;
const long long N = 99999, M = 999999;
typedef pair<long long, long long> PII;
priority_queue<PII, vector<PII>, greater<PII> > q;
long long n, p, c, k, x, y, l;
long long pre[N];//連結串列頭
long long d[N];//dis距離陣列
bool f[N];//標記陣列
struct Node {
	long long v, next, len;//鏈式前向星
} a[M * 2];
void add(long long u, long long v, long long len) {
	a[++k] = {v, pre[u], len};
	pre[u] = k;
}//建邊
int dijkstra(long long h) {
	d[h] = 0;
	q.push({0, h});
	while (!q.empty()) {
		PII b = q.top();
		long long dis = b.first;
		long long pi = b.second;
		q.pop();
		if (f[pi]) continue;
		f[pi] = true;
		for (long long i = pre[pi]; i; i = a[i].next) {
			long long to = a[i].v;
			if (d[to] > dis + a[i].len) {
				d[to] = dis + a[i].len;
				q.push({d[to], to});
			}
		}
	}
	return d[3];
}//dijstra堆最佳化
int main() {
	//全開longlong防止資料爆掉
	cin >> x >> y; //讀入x,y;
	//使用鏈式前向星進行建圖
	add(1, 2, x);
	add(2, 3, y);
	memset(d, 0x3f, sizeof(d));
	memset(f, 0, sizeof(f));
	cout << dijkstra(1); //開始跑dijstra堆最佳化
	return 0;
}

時間複雜度
總共需要遍歷 \(2\) 條邊,插入資料修改小根堆的時間複雜度為 \(O(N \log_2(N))\) 所以時間複雜度為 \(O(3*\log_2(3))\)。因為對於 稀疏圖 來說邊數與點數很接近,所以可以看做為 \(O(N \log_2(N))\)。但是對於 稠密圖 來說邊數接近點數的平方個,如果稠密圖使用堆最佳化版的 Dijkstra 演算法,那麼時間複雜度將會是 \(O(n^2*\log_2(n))\),顯然不如直接使用樸素 Dijkstra 演算法。所以堆最佳化版的 Dijkstra 演算法更適用於稀疏圖 ,而樸素 Dijkstra 演算法更適用於稠密圖。
綜上所述:本程式的時間複雜度為 \(O(3*log_2(3))\)
最後祝大家早日成為大牛

相關文章