涉及知识点:
solution:
- (这个题乍一看没啥好的思路,我们把伤害都转化成两点之间的路径长度)
- (问题转化成考察最短路的应用,如果不会写最短路建议先学习最短路)
- (先求出发点s到所有点到的最短路,这个路径要求是白天模式的路径)
- (然后再求终点t到所有点的最短路,这个路径要求是夜间模式的路径)
- (把出发点到每个点的最短路存到数组dis1中,把终点到每个点的最短路存到数组dis2中)
- (如果在第i个位置切换模式,那最短路径 = dis1[i] + dis2[i])
- (那么答案其实就是Min(dis1[i] + dis2[i])(1<=i<=n))
- (但是题目要求切换夜间模式的点不能小于难度!所以必须要从后往前遍历记录最小值)
std:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll inf = 1e18;
const int maxx = 1e5+10;
int n,m;
ll dis1[maxx],dis2[maxx],a[maxx];
struct node{
int to;
ll w;
friend bool operator <(node p1,node p2){
return p1.w > p2.w;
}//小优先
};
vector<node> v1[maxx];
vector<node> v2[maxx];
priority_queue<node> q;
void spfa(int s)
{
fill(dis1+1,dis1+1+n,inf);
dis1[s] = 0;
while(!q.empty())
q.pop();
q.push(node{s,0});
while(!q.empty())
{
node x = q.top();q.pop();
int k = x.to;
if(x.w > dis1[x.to])
continue;
for(int i=0;i<v1[k].size();i++){
if(dis1[v1[k][i].to] > x.w + v1[k][i].w){
dis1[v1[k][i].to] = x.w + v1[k][i].w;
q.push(node{v1[k][i].to,dis1[v1[k][i].to]});
}
}
}
}
void spfa2(int s)
{
fill(dis2+1,dis2+1+n,inf);
dis2[s] = 0;
while(!q.empty())
q.pop();
q.push(node{s,0});
while(!q.empty())
{
node x = q.top();q.pop();
if(x.w > dis2[x.to])
continue;
int k = x.to;
for(int i=0;i<v2[k].size();i++){
if(dis2[v2[k][i].to] > x.w + v2[k][i].w){
dis2[v2[k][i].to] = x.w + v2[k][i].w;
q.push(node{v2[k][i].to,dis2[v2[k][i].to]});
}
}
}
}
int main()
{
cin>>n>>m;
int x,y,l1,l2,t,s;
for(int i=1;i<=m;i++){
cin>>x>>y>>l1>>l2;
v1[x].push_back({y,l1});
v1[y].push_back({x,l1});
v2[x].push_back({y,l2});
v2[y].push_back({x,l2});
}
scanf("%d%d",&t,&s);
spfa(t);spfa2(s);
ll ans = inf;
for(int i=n;i>=1;i--){
ans = min(ans,dis1[i]+dis2[i]);
a[i] = ans;
}
for(int i=1;i<=n;i++){
printf("%lld
",a[i]);
}
return 0;
}