BD202301公园
题目详情
题目简述:两个人起点不同,需要抵达同一终点,过程中若两人同行则消耗减少固定值,求抵达终点两人消耗值的最小值。
思路:1. 第一反应是最短路,先将第一个人抵达各点的最小消耗求出来,再对第二个人求最短路,以两个人的总消耗作为目标值。时间复杂度由求最短路的算法决定,输入节点数N和路径数M<=4e4,稀疏图,可用堆优化Dijstra,O(mlogm)。
2. 写完第一个人再写第二个人的时候发现,不能用最短路,比较适合BFS,得同时更新第二个人到各节点的最短路和两个人共同到某一节点的最小消耗。
3. 接着发现其实可以通过跑三遍Dijstra解决,其中第三遍Dijstra的初始节点集为两人能共同抵达的节点,两个人在相遇后一起走一定是比相遇再分开优的。
4. 数据溢出问题卡了我一个点。
代码
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
vector<int> Dijstra(int s, int cost, vector<vector<int>> &g){
int N = g.size()-1;
vector<int> distT(N+1, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
pq.emplace(0, s); distT[s] = 0;
while(!pq.empty()){
auto [dx, x] = pq.top(); pq.pop();
if(dx > distT[x]) continue;
int temp_dist = dx + cost;
for(auto &y : g[x])
if(temp_dist < distT[y]){
distT[y] = temp_dist;
pq.emplace(temp_dist, y);
}
}
return distT;
}
vector<int> BFS(int cost, vector<vector<int>> &g,
vector<int> &distT, vector<int> &distF){
int N = g.size()-1;
vector<int> distTF(N+1, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
for(int i = 1; i <= N; i++) {
LL temp_dist = (LL)distT[i]+distF[i];
if(temp_dist < INT_MAX){
distTF[i] = temp_dist;
pq.emplace(distTF[i], i);
}
}
while(!pq.empty()){
auto [dx, x] = pq.top(); pq.pop();
if(dx > distTF[x]) continue;
int temp_dist = dx + cost;
for(auto &y : g[x])
if(temp_dist < distTF[y]){
distTF[y] = temp_dist;
pq.emplace(temp_dist, y);
}
}
return distTF;
}
int main( )
{
int TE, FE, S;
cin>>TE>>FE>>S;
int T, F, N, M;
cin>>T>>F>>N>>M;
vector<vector<int>> g(N+1);
for(int i = 0; i < M; i++){
int X, Y;
cin>>X>>Y;
g[X].emplace_back(Y);
g[Y].emplace_back(X);
}
vector<int> distT = Dijstra(T, TE, g);
vector<int> distF = Dijstra(F, FE, g);
vector<int> distTF = BFS(TE + FE - S, g, distT, distF);
cout<<(distTF[N] < INT_MAX ? distTF[N] : -1)<<endl;
return 0;
}
咸鱼翻身失败