思路:BFS
有点费脑子,首先你需要想到,我们其实不能走这两个起点的最短路径,而是需要走一个两者共同走过的路。
我们可以轻松解决其距离问题,但是对于这个共同路径我们需要怎么找呢?
答案是,找路径的共同遍历点。也就是两个人走过的那个点。那要怎么找呢?枚举就行了。(核心)
那么,既然找到了中间的公共点,其实就直接找以各个点作为公共点然后总计消耗为多少就可以了,可以逆向思维,终点到共同点这一条路径是两人共同走的路径,也就是两人的消耗之和减去能够减少的能耗。两人到公共点的距离其实就是两个人到达这里的消耗之和,就全部加起来就是总消耗了,就这样枚举出最小值就可以。
注意:这里为什么需要BFS三遍,是因为第一遍需要确认起点到终点有没有路径;
第二遍第三遍其实就是为了后面找终点,两个起点共同经过的公共点才这样的,times参数表示访问次数。如代码所见,访问次数为3的时候才能说是公共点,也就是终点出发经过的点,两个起点出发都经过的点。
#include<bits/stdc++.h>
using namespace std;
vector<int>g[40010];
int visit[40010];
int disn[40010];
int disf[40010];
int dist[40010];
int te,fe,s,t,f,n,m;
void bfs(int start,int times,int a[]){
queue<int>q;
a[start]=0;
visit[start]++;
q.push(start);
while(!q.empty()){
int tmp=q.front();
q.pop();
for(auto&cao:g[tmp]){
if(visit[cao]==times)continue;
a[cao]=a[tmp]+1;
visit[cao]++;
q.push(cao);
}
}
}
int main( )
{
cin>>te>>fe>>s;
cin>>t>>f>>n>>m;
while(m--){
int x,y;
cin>>x>>y;
g[x].push_back(y);
g[y].push_back(x);
}
bfs(n,1,disn);//首先进行终点遍历操作,这一定是第一个操作,用来判断能不能到达两个起点。
if(!visit[t]||!visit[f]){
cout<<-1;
return 0;
}
int res=INT_MAX;
bfs(t,2,dist);
bfs(f,3,disf);
for(int i=1;i<=n;i++){
if(visit[i]==3){
res=min(res,dist[i]*te+disf[i]*fe+disn[i]*(te+fe-s));
}
}
cout<<res;
return 0;
}