[AHOI2017初中组]guide
题目描述
农场主John最近在网上买了一辆新车,在购买汽车配件时,John不小心点了两次“提交”按钮。导致汽车上安装了两套GPS系统,更糟糕的是John在使用GPS导航时,两套系统常常给出不同的路线。从地图上看,John居住的地区有N(2 ≤ N ≤ 100,000)个十字路口和M(1 ≤ M ≤ 500,000)条限定通行方向的道路。第i条道路连接路口 A_i (1 ≤ A_i ≤ N)和B_i (1 ≤ B_i ≤ N),两个路口之间可能连接有多条道路。允许双向通的道路是将两条单向通⾏的道路隔开所形成的。
John的家在路口1位置,农场在路口N的位置。John可以沿着系列单向道路从家驾车到农场。所有GPS系统的底层地图信息都是⼀样的,区别仅在于对每一条道路的通⾏时间计算不同。对于第i条道路第一套GPS系统计算通行时间为P_i个单位时间,而第二套GPS系统则给出Q_i个单位时间。(所有道路的通行时间都是范围在1到100,000之间的整数)John想要驾车从家到农场。可是,一路上GPS系统总是不厌其烦的提醒John(请从路口X开往路口Y),这是由于John选取了某套GPS系统建议的路径,而另一套GPS系统则认为这不是从路口X到农场的最短路径。我们称之为GPS系统的抱怨。
请你计算一下如果John选择合适的路径到达农场能听到的最少GPS系统的抱怨数 。如果John经过某条道路两套GPS系统都发出抱怨,则抱怨总数加2。
输入输出格式
输入格式:
第一行,两个整数N和M。
接下来M行,其中第i行描述了道路i的信息,A_i B_i P_i Q_i。
输出格式:
一个整数,表示John一路上能听到的最小抱怨数。
输入输出样例
输出样例#1:
1
闲话:
2017考完这题后,我们老师才开始讲最短路。。。然后讲了1个多月。。。
分析:
本题算法除了最短路我也不知道还能想到什么了。。。
主要在于要跑3遍SPFA,首先2遍按两套系统给出的不同值算最短路,然后按每条边的抱怨值重新构图,再做一次最短路求出答案。
CODE:
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <queue> 7 using namespace std; 8 const int M=1000005; 9 const long long oo=(1ll<<61); 10 int nxt[M],to[M],head[M],inq[M],tot,rtot; 11 int rnxt[M],rto[M],rhead[M]; 12 int adj1[M],adj2[M],adj3[M]; 13 long long dist1[M],dist2[M],dist3[M]; 14 int n,m; 15 void add(int u,int v,int w1,int w2){ 16 nxt[++tot]=head[u];head[u]=tot;to[tot]=v; 17 adj1[tot]=w1;adj2[tot]=w2; 18 return; 19 } 20 void radd(int u,int v,int w){ 21 rnxt[++rtot]=rhead[u];rhead[u]=rtot;rto[rtot]=v;adj3[rtot]=w; 22 return; 23 } 24 void spfa1(){ 25 queue <int> Q; 26 Q.push(n);inq[n]=1;dist1[n]=0; 27 while (!Q.empty()){ 28 int top=Q.front();Q.pop(),inq[top]=0; 29 for (int i=head[top];i;i=nxt[i]) 30 if (dist1[top]+adj1[i]<dist1[to[i]]){ 31 dist1[to[i]]=dist1[top]+adj1[i]; 32 if (!inq[to[i]]) Q.push(to[i]),inq[to[i]]=1; 33 } 34 } 35 return; 36 } 37 void spfa2(){ 38 queue <int> Q; 39 Q.push(n);inq[n]=1;dist2[n]=0; 40 while (!Q.empty()){ 41 int top=Q.front();Q.pop(),inq[top]=0; 42 for (int i=head[top];i;i=nxt[i]) 43 if (dist2[top]+adj2[i]<dist2[to[i]]){ 44 dist2[to[i]]=dist2[top]+adj2[i]; 45 if (!inq[to[i]]) Q.push(to[i]),inq[to[i]]=1; 46 } 47 } 48 return; 49 } 50 void spfa3(){ 51 queue <int> Q; 52 Q.push(1);inq[1]=1;dist3[1]=0; 53 while (!Q.empty()){ 54 int top=Q.front();Q.pop(),inq[top]=0; 55 for (int i=rhead[top];i;i=rnxt[i]) 56 if (dist3[top]+adj3[i]<dist3[rto[i]]){ 57 dist3[rto[i]]=dist3[top]+adj3[i]; 58 if (!inq[rto[i]]) Q.push(rto[i]),inq[rto[i]]=1; 59 } 60 } 61 return; 62 } 63 int main(){ 64 scanf("%d%d",&n,&m); 65 for (int i=1;i<=n;i++) dist1[i]=dist2[i]=dist3[i]=oo; 66 for (int i=1;i<=m;i++){ 67 int u,v,w1,w2; 68 scanf("%d%d%d%d",&u,&v,&w1,&w2); 69 add(v,u,w1,w2); 70 } 71 spfa1();spfa2(); 72 for (int i=1;i<=n;i++) 73 for (int j=head[i];j;j=nxt[j]) 74 radd(to[j],i,(dist1[i]+adj1[j]>dist1[to[j]])+(dist2[i]+adj2[j]>dist2[to[j]])); 75 spfa3(); 76 cout<<dist3[n]; 77 return 0; 78 }