问题描述
约翰在他的新车上装了两个导航系统(GPS),但这两个GPS选择的导航线路常常不同,约翰很是恼火。
约翰所在的小镇地图由N个路口和M条单向道路构成,两个路口间可能有多条道路相连。约翰的家在1号路口,他的农场在N号路口。约翰从家出发,可以经过一系列的道路,最终到达农场。
两个GPS用的都是上述地图,但是,它们计算时间的算法不同。比如,经过第i条道路,1号GPS计算出的时间是Pi分钟,而2号GPS算出的时间是Qi分钟。
约翰想要驾车从家到农场,但是,如果一个GPS认为约翰当前行走的这条路不在它算出的最短路径中,该GPS就会大声抱怨约翰走错了路(每个GPS会算出所有最短路,只要你在其中一条上最短路上它都不会抱怨)。更倒霉的是,有可能两个GPS会同时抱怨约翰当前走的路不是它们推荐的。
请帮助约翰计算,从家到农场过程中,选择怎样的路径才能使得GPS抱怨的次数最少,请算出这个最少的抱怨次数。如果一条路上两个GPS都在抱怨,算两次(+2)抱怨。
输入格式
第1行两个空格间隔的整数,N和M
接下来M行,每行描述一条道路。第i行描述第i条道路,由四个空格间隔的整数构成,Ai,Bi,Pi,Qi,分别表示该条道路的起点、终点、1号GPS计算的耗时、2号GPS计算的耗时。
输出格式
一个整数,表示所求答案。
样例输入
5 7
3 4 7 1
1 3 2 20
1 4 17 18
4 5 25 3
1 2 10 1
3 5 4 14
2 4 6 5
样例输出
1
题解
三次spfa()
如果dis[y]-dis[x]==len[i]那么道路i在最短路上
代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
#define maxn1 10004
#define maxn2 100006
#define inf 1e9
int Last[maxn2],End[maxn2],Next[maxn2],St[maxn2],l1[maxn2],l2[maxn2],l3[maxn2];
int n,m;
int Last1[maxn2],End1[maxn2],Next1[maxn2];
int cnt;
int dis1[maxn1],dis2[maxn1],dis3[maxn1];
bool mark[maxn1];
queue<int>q;
void insert(int x,int y,int z1,int z2)
{
Next[++cnt]=Last[x];
Last[x]=cnt;
End[cnt]=y;
St[cnt]=x;
l1[cnt]=z1;
l2[cnt]=z2;
Next1[cnt]=Last1[y];
Last1[y]=cnt;
End1[cnt]=x;
}
void spfa1(){
int i,j;
for(i=1;i<=n-1;i++) dis1[i]=inf;
memset(mark,false,sizeof(mark));
q.push(n);
mark[n]=true;
while(q.size())
{
int s=q.front();
q.pop();
mark[s]=false;
for(i=Last[s];i;i=Next[i])
{
int en=End[i];
if(dis1[en]>dis1[s]+l1[i])
{
dis1[en]=dis1[s]+l1[i];
if(mark[en]==false){
mark[en]=true;
q.push(en);
}
}
}
}
}
void spfa2(){
int i,j;
for(i=1;i<=n-1;i++) dis2[i]=inf;
memset(mark,false,sizeof(mark));
q.push(n);
mark[n]=true;
while(q.size())
{
int s=q.front();
q.pop();
mark[s]=false;
for(i=Last[s];i;i=Next[i])
{
int en=End[i];
if(dis2[en]>dis2[s]+l2[i])
{
dis2[en]=dis2[s]+l2[i];
if(mark[en]==false){
mark[en]=true;
q.push(en);
}
}
}
}
}
void spfa3(){
int i,j;
for(i=2;i<=n;i++) dis3[i]=inf;
memset(mark,false,sizeof(mark));
q.push(1);
mark[1]=true;
while(q.size())
{
int s=q.front();
q.pop();
mark[s]=false;
for(i=Last1[s];i;i=Next1[i])
{
int en=End1[i];
if(dis3[en]>dis3[s]+l3[i])
{
dis3[en]=dis3[s]+l3[i];
if(mark[en]==false){
mark[en]=true;
q.push(en);
}
}
}
}
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
int x,y,z1,z2;
scanf("%d%d%d%d",&x,&y,&z1,&z2);
insert(y,x,z1,z2);
}
spfa1();
spfa2();
for(i=1;i<=m;i++){
int tx,ty;
tx=St[i];
ty=End[i];
if(dis1[ty]-dis1[tx]!=l1[i]) l3[i]++;
if(dis2[ty]-dis2[tx]!=l2[i]) l3[i]++;
}
spfa3();
cout<<dis3[n];
}