题目描述
题目分析
单源最短路径问题。由数据规模可知,使用Bellman-Ford算法可能超时,且没有负边,故使用Dijksra算法。为了便于计算最短路径,将隔离时间加入到边的权值中。使用Map容器储存最小边,便于存取。
我的代码
在C++中,如果使用std::map
容器,其默认的排序方式是按照key的升序进行排序。如果key是pair
类型,那么默认情况下会按照pair
的字典序进行排序。也就是说,会先比较第一个元素,如果第一个元素相等,则比较第二个元素。
例如,对于std::map<std::pair<int, int>, int>
,会按照pair的第一个元素升序排序,如果第一个元素相等,则按照第二个元素升序排序。
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const int MAX_V = 1002;
const int MAX_E = 10002;
int cost[MAX_V][MAX_V]; //cost[u][v]表示边e=(u,v)的权值
int d[MAX_V]; //记录最短距离
int value[MAX_V]; //记录隔离时间
map<pair<int, int>, int> M; //堆存放最小边
map<pair<int, int>, int>::iterator it; //迭代器
int v;
int e;
int main() {
/*初始化*/
cin >> v >> e;
for (int i = 0; i < MAX_V; i++)
{
for (int j = 0; j < MAX_V; j++) {
cost[i][j] = 0x3f3f3f3f;
}
}
for (int i = 1; i <= v; i++)
{
cin >> value[i];
if (i == v) {
value[i] = 0; //最后一个城市不用计算隔离时间
}
d[i] = 0x3f3f3f3f;
d[1] = 0;
pair<int, int> P(d[i], i);
M.insert(pair<pair<int, int>, int>(P, i));
}
for (int i = 1; i <= e; i++)
{
int s;
int t;
int lenth;
cin >> s >> t >> lenth;
cost[s][t] = lenth + value[t];
cost[t][s] = lenth + value[s];
}
/*Dijkstra算法*/
while (!M.empty()) {
it = M.begin();
//int lenth = (*it).first;
int s = (*it).second; //获取当前搜索点
it = M.erase(it);
for (int i = 1; i <= v; i++)
{
if (d[i] > d[s] + cost[s][i]) {
pair<int, int> P(d[i], i);
M.erase(P);//从容器中删除
d[i] = d[s] + cost[s][i];
pair<int, int> P2(d[i], i);
M.insert(pair<pair<int, int>, int>(P2, i));//覆盖原最短路径
}
}
}
/*获取结果*/
cout << d[v];
return 0;
}