最短路的变形问题
普通的最短路,选取离出发点最近的一个点对其他的点进行优化
本题则每次选取最短的边作为计算的单位 ,对边的两端点所连接两条边进行优化。
最后在与结点n相连接的边中选择最小的即是答案
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define LL long long
using namespace std;
const int maxn=1e5+7;
const int INF=1e9+7;
int n,m;
struct Edge{
int u,v;
LL c,t;
}edge[maxn];
struct min_edge{
int lin;
LL min_length;
min_edge(int lin,LL min_length):lin(lin),min_length(min_length){} //方便装入队列
bool operator<(const min_edge&a)const{ //构造优先队列 此处 >则从小到大排 <则从大到小排
return min_length>a.min_length;
}
};
vector<int>Map[maxn]; //储存与点连接的的边的编号
int vis[maxn];
LL dis[maxn];
LL jdz(LL a,LL b){
if(a>b)return a-b;
else return b-a;
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<=n;i++)Map[i].clear();
for(int i=0;i<m;i++)dis[i]=INF;
memset(vis,0,sizeof(vis)); //初始化
priority_queue<min_edge>Q; //最短边
for(int i=0;i<m;i++){ //储存边的信息
scanf("%d%d%lld%lld",&edge[i].u,&edge[i].v,&edge[i].c,&edge[i].t);
if(min(edge[i].u,edge[i].v)==1){
dis[i]=edge[i].t;
Q.push(min_edge(i,edge[i].t));
}
Map[edge[i].u].push_back(i);//储存与点连接的的边的编号
Map[edge[i].v].push_back(i);
}
while(!Q.empty()) { //dijkstra
min_edge now=Q.top();Q.pop();
int x=now.lin; // 当前最短的边
if(vis[x])continue;
vis[x]=1;
int L1=edge[x].u,L2=edge[x].v; //边的两端点
for(int i=0;i<Map[L1].size();i++) { //优化L1端点的边
int y=Map[L1][i];
int time=jdz(edge[x].c,edge[y].c);
if(dis[y]>dis[x]+time+edge[y].t){
dis[y]=dis[x]+time+edge[y].t;
Q.push(min_edge(y,dis[y]));
}
}
for(int i=0;i<Map[L2].size();i++) { //优化L2端点的边
int y=Map[L2][i];
int time=jdz(edge[x].c,edge[y].c);
if(dis[y]>dis[x]+time+edge[y].t){
dis[y]=dis[x]+time+edge[y].t;
Q.push(min_edge(y,dis[y]));
}
}
}
LL ans=INF;
for(int i=0;i<Map[n].size();i++) {
ans=min(ans,dis[Map[n][i]]);
}
printf("%lld\n",ans);
}
return 0;
}