- 考察最优解具有的性质:dest,src1,src2结点到某个公共结点的最短路
- 堆优化版迪杰斯特拉算法涉及修改堆中结点的情况,但C++ STL本身并不支持堆结点修改。也无法找到那个堆结点,删除再插入新的。
- 考虑迪杰斯特拉算法的执行过程。后面出队的结点的dist一定大于等于前面出队的结点。所以如果后面结点在前面的结点已经遇到过即这个后面遇到的结点在堆中存储的路径长度大于现有长度dist则直接将这个结点舍去。避免重复的松弛操作。
class Solution {
struct cmp{
bool operator () (pair<int,long> a, pair<int,long> b){
if(a.second < 0) return true;
if(b.second < 0) return false;
return a > b;
}
};
public:
long long minimumWeight(int n, vector<vector<int>>& edges, int src1, int src2, int dest) {
long long dist1[n];
long long dist2[n];
long long dist3[n];
memset(dist1,-1,n*sizeof(long long));
memset(dist2,-1,n*sizeof(long long));
memset(dist3,-1,n*sizeof(long long));
vector<pair<int,int>> adjmap[n];
vector<pair<int,int>> adjmap_fan[n];
for(int i = 0;i<edges.size();i++)
{
adjmap[edges[i][0]].push_back(make_pair(edges[i][1],edges[i][2]));
adjmap_fan[edges[i][1]].push_back(make_pair(edges[i][0],edges[i][2]));
}
dijktra(n,adjmap,src1,dist1);dijktra(n,adjmap,src2,dist2); dijktra(n,adjmap_fan,dest,dist3);
long long ans = -1;
for(int i = 0;i<n;i++)
{
if(dist1[i] >= 0 && dist2[i] >= 0 && dist3[i] >=0) //均可以到达
{
if(ans < 0) ans = dist1[i] + dist2[i] + dist3[i];
else ans = min(ans,dist1[i] + dist2[i] + dist3[i]);
}
}
return ans;
}
void dijktra(int n,vector<pair<int,int>> adjmap[],int src,long long dist[])
{
dist[src] = 0; //到源节点的距离为0
priority_queue<pair<int,long long>,vector<pair<int,long long>>,cmp> q; q.push(make_pair(src,0));
while(!q.empty())
{
int u = q.top().first;
if(q.top().second > dist[u] ) {q.pop();continue;} //注意这里的舍弃操作
q.pop();
//relax
for(pair<int,int> a:adjmap[u])
{
int v = a.first; int w = a.second;
if(dist[v] == -1 || (dist[v] >= 0 && dist[v] > dist[u] +(long long) w ))
{
dist[v] = dist[u] +(long long) w ;
q.push(make_pair(v,dist[v]));
}
}
}
}
};
- 同时,总结下cmp结构体里的operator:
struct cmp{
bool operator () (pair<int,long> a, pair<int,long> b){
if(a.second < 0) return true;
if(b.second < 0) return false;
return a > b;
}
};
- 如果返回真,则程序将a放在b后面,否则如果返回假,则程序将b放在a后面。