最小堆优化
- 优化的点是每次直接通过最小堆的堆顶找到最短路径最小的未搜索的点
- 省去了一层遍历
const int N = 1e6 + 10, INF = 0x3f3f3f3f;
int h[N], e[N], ne[N], w[N], n, m, idx = 0, d[N];
bool visited[N];
void add(int a, int b, int c){e[idx] = b; ne[idx] = h[a]; w[idx] = c; h[a] = idx++;}
int dijkstra(int s)
{
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> m_heap;
fill(d, d + N, INF);
d[s] = 0;
m_heap.push({0, 1});
while(m_heap.size())
{
int u = m_heap.top().second, ud = m_heap.top().first;
m_heap.pop();
if(visited[u])
continue;
visited[u] = true;
for(int v = h[u]; v != -1; v = ne[v])
{
int j = e[v];
if(visited[j] == false && ud + w[v] < d[j])
{
d[j] = ud + w[v];
m_heap.push({d[j], j});
}
}
}
return d[n] == INF ? -1 : d[n];
}
邻接矩阵版
const int N = 510, INF = 0x3f3f3f3f;
int G[N][N], d[N], n, m, a, b, c;
bool visited[N];
int Dijkstra(int s)
{
memset(d, 0x3f, sizeof d);
d[s] = 0;
for(int i = 1; i <= n; ++i)
{
int u = -1;
for(int j = 1; j <= n; ++j)
if(visited[j] == false && (u == -1 || d[j] < d[u]))
u = j;
visited[u] = true;
for(int v = 1; v <= n; ++v)
if(visited[v] == false && G[u][v] != INF && G[u][v] + d[u] < d[v])
d[v] = d[u] + G[u][v];
}
return d[n] == INF ? -1 : d[n];
}
int main()
{
cin >> n >> m;
fill(G[0], G[0] + N * N, INF);
while(m--)
{
cin >> a >> b >> c;
G[a][b] = min(G[a][b], c);
}
cout << Dijkstra(1);
return 0;
}
邻接表版
const int N = 1e5 + 10, INF = 0x3f3f3f3f;
int h[N], e[N], ne[N], w[N], n, m, idx = 0, d[N];
bool visited[N];
void add(int a, int b, int c)
{
e[idx] = b; ne[idx] = h[a]; w[idx] = c; h[a] = idx++;
}
int Dijkstra(int s)
{
fill(d, d + N, INF);
d[s] = 0;
for(int i = 1; i <= n; ++i)
{
int u = -1;
for(int j = 1; j <= n; ++j)
if(visited[j] == false && (u == -1 || d[j] < d[u]))
u = j;
visited[u] = true;
for(int v = h[u]; v != -1; v = ne[v])
{
int j = e[v];
if(visited[j] == false && w[v] + d[u] < d[j])
d[j] = w[v] + d[u];
}
}
return d[n] == INF ? -1 : d[n];
}
int main()
{
fill(h, h + N, -1);
cin >> n >> m;
for(int i = 0; i < m; ++i)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
cout << Dijkstra(1);
return 0;
}
PAT 1003 Emergency
- 注意这里是无向图
- 并且是多条路径、多点权的情况(一般都直接另加数组,配合条件判断使用)
const int N = 1e6, INF = 0x3f3f3f3f;
int h[N], e[N], ne[N], w[N], rt[N], d[N], num[N], tnum[N], n, m, c1, c2, idx = 0;
bool visited[N];
void add(int a, int b, int c){
e[idx] = b; ne[idx] = h[a]; w[idx] = c; h[a] = idx++;}
void Dijkstra(int start, int end)
{
fill(d, d + N, INF);
fill(num, num + N, 0);
fill(tnum, tnum + N, 0);
d[start] = 0;
num[start] = 1;
tnum[start] = rt[start];
for(int i = 0; i < n; ++i)
{
int u = -1;
for(int j = 0; j < n; ++j)
if(visited[j] == false && (u == -1 || d[j] < d[u]))
u = j;
if(u == -1) return ;
visited[u] = true;
for(int v = h[u]; v != -1; v = ne[v])
{
int j = e[v];
if(visited[j] == false)
{
if(d[u] + w[v] < d[j])
{
d[j] = d[u] + w[v];
num[j] = num[u];
tnum[j] = rt[j] + tnum[u];
}
else if(d[u] + w[v] == d[j])
{
num[j] += num[u];
if(tnum[u] + rt[j] > tnum[j])
tnum[j] = rt[j] + tnum[u];
}
}
}
}
}
int main()
{
fill(h, h + N, -1);
cin >> n >> m >> c1 >> c2;
for(int i = 0; i < n; ++i)
cin >> rt[i];
for(int i = 0; i < m; ++i)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
add(b, a, c);
}
Dijkstra(c1, c2);
cout << num[c2] << " " << tnum[c2] << endl;
return 0;
}
PAT 1030 Travel Plan
const int N = 1e3, INF = 0x3f3f3f3f;
int h[N], e[N], ne[N], w1[N], w2[N], n, m, mstart, mend, idx = 0;
int d[N], c[N];
bool visited[N];
int pre[N];
void add(int a, int b, int c, int d){
e[idx] = b; ne[idx] = h[a]; w1[idx] = c; w2[idx] = d; h[a] = idx++;}
void Dijkstra(int s)
{
fill(d, d + N, INF); fill(c, c + N, INF); d[s] = 0; c[s] = 0;
for(int i = 0; i < n; ++i)
{
int u = -1;
for(int j = 0; j < n; ++j)
if(visited[j] == false && (n == -1 || d[j] < d[u]))
u = j;
visited[u] = true;
for(int v = h[u]; v != -1; v = ne[v])
{
int j = e[v];
if(visited[j] == false)
{
if(w1[v] + d[u] < d[j])
{
d[j] = w1[v] + d[u];
c[j] = w2[v] + c[u];
pre[j] = u;
}
else if(w1[v] + d[u] == d[j])
{
if(w2[v] + c[u] < c[j])
{
c[j] = w2[v] + c[u];
pre[j] = u;
}
}
}
}
}
}
void DFS(vector<int> &ret, int cur)
{
if(cur == mstart)
{
ret.push_back(cur);
return;
}
DFS(ret, pre[cur]);
ret.push_back(cur);
}
int main()
{
fill(h, h + N, -1);
cin >> n >> m >> mstart >> mend;
while(m--)
{
int a, b, c, d;
cin >> a >> b >> c >> d;
add(a, b, c, d);
add(b, a, c, d);
}
Dijkstra(mstart);
vector<int> ret;
DFS(ret, mend);
for(auto a : ret)
cout << a << " ";
cout << d[mend] << " " << c[mend];
return 0;
}
int G[N][N], C[N][N];
void Dijkstra(int s)
{
fill(d, d + N, INF); fill(c, c + N, INF); d[s] = 0; c[s] = 0;
for(int i = 0; i < n; ++i)
{
int u = -1;
for(int j = 0; j < n; ++j)
if(visited[j] == false && (n == -1 || d[j] < d[u]))
u = j;
visited[u] = true;
for(int v = 0; v < n; ++v)
{
if(visited[v] == false && G[u][v] != INF)
{
if(d[u] + G[u][v] < d[v])
{
d[v] = d[u] + G[u][v];
c[v] = c[u] + C[u][v];
pre[v] = u;
}
else if(d[u] + G[u][v] == d[v])
{
if(c[u] + C[u][v] < c[v])
{
c[v] = c[u] + C[u][v];
pre[v] = u;
}
}
}
}
}
}
int main()
{
memset(G, 0x3f, sizeof(G));
memset(C, 0x3f, sizeof(C));
cin >> n >> m >> mstart >> mend;
while(m--)
{
int a, b;
cin >> a >> b;
cin >> G[a][b] >> C[a][b];
G[b][a] = G[a][b]; C[b][a] = C[a][b];
}
Dijkstra(mstart);
DFS(mend);
cout << d[mend] << " " << c[mend];
return 0;
}