Guide AHOI2017 洛谷P3720
Description
农场主John最近在网上买了一辆新车,在购买汽车配件时,John不小心点了两次“提交”按钮。导致汽车上安装了两套GPS系统,更糟糕的是John在使用GPS导航时,两套系统常常给出不同的路线。从地图上看,John居住的地区有N个十字路口和M条限定通行方向的道路。第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。
Input
第一行,两个整数N和M。接下来M行,其中第i行描述了道路i的信息,A_i B_i P_i Q_i。
Output
一个整数,表示John一路上能听到的最小抱怨数。
Hint
2≤N≤100000,1≤M≤500000。
Solution
洛谷上面的题都坑爹得一批,指针也坑爹得一批,然后这道题成功地两条都应验了。。。
呃这道题首先是个最短路然后要建三张图跑三次,Dijkstra和SPFA好像都可以不过为了复习SPFA我还是写的SPFA即使它非常地坑人。。嗯然后两个GPS的最短路径各跑一遍,然后用一个for循环预处理出第三个图的边权,也就是这个听抱怨的图的边权,然后只要他没有听GPS1或者2的都要++,都没听就会++两次,然后最后再跑一次SPFA就可以了。
注意事项:
1.指针不能sizeof我要是再被这个坑了我就去自杀一百遍。。。
2.这个因为最后到的是n所以既然是单源最短路径就要从n开始,而且,而且,而且,要,建,反图。
3.好的我还是傻逼还是非常地弱,没了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define maxn 500005
#define inf 0x3f3f3f3f
using namespace std;
int n,m,node1,x,y,z1,z2,node2,node3;
struct Edge{
int u;
int v;
int w;
int next;
}edge1[maxn],edge2[maxn],edge3[maxn];
int first1[maxn],last1[maxn],first2[maxn];
int last2[maxn],first3[maxn],last3[maxn];
int dist1[maxn],dist2[maxn],dist3[maxn];
bool vis1[maxn],vis2[maxn],vis3[maxn];
void addedge1(int u,int v,int w){
edge1[++node1]=(Edge){u,v,w,0};
if(first1[u]==0)first1[u]=node1;
else edge1[last1[u]].next=node1;
last1[u]=node1;
}
void addedge2(int u,int v,int w){
edge2[++node2]=(Edge){u,v,w,0};
if(first2[u]==0)first2[u]=node2;
else edge2[last2[u]].next=node2;
last2[u]=node2;
}
void addedge3(int u,int v,int w){
edge3[++node3]=(Edge){u,v,w,0};
if(first3[u]==0)first3[u]=node3;
else edge3[last3[u]].next=node3;
last3[u]=node3;
}
void init(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&x,&y,&z1,&z2);
addedge1(y,x,z1);
addedge2(y,x,z2);
addedge3(y,x,0);
}
}
void spfa1(int s,int *d){
queue<int>pq;
memset(d,inf,sizeof(dist1));
d[s]=0;
vis1[s]=true;
pq.push(s);
while(!pq.empty()){
int u=pq.front();
pq.pop();
vis1[u]=false;
for(int k=first1[u];k;k=edge1[k].next){
int v=edge1[k].v;
if(d[u]+edge1[k].w<=d[v]){
d[v]=d[u]+edge1[k].w;
if(!vis1[v]){
vis1[v]=true;
pq.push(v);
}
}
}
}
}
void spfa2(int s,int *d){
queue<int>pq;
memset(d,inf,sizeof(dist2));
d[s]=0;
vis2[s]=true;
pq.push(s);
while(!pq.empty()){
int u=pq.front();
pq.pop();
vis2[u]=false;
for(int k=first2[u];k;k=edge2[k].next){
int v=edge2[k].v;
if(d[u]+edge2[k].w<=d[v]){
d[v]=d[u]+edge2[k].w;
if(!vis2[v]){
vis2[v]=true;
pq.push(v);
}
}
}
}
}
void spfa3(int s,int *d){
queue<int>pq;
memset(d,inf,sizeof(dist3));
d[s]=0;
vis3[s]=true;
pq.push(s);
while(!pq.empty()){
int u=pq.front();
pq.pop();
vis3[u]=false;
for(int k=first3[u];k;k=edge3[k].next){
int v=edge3[k].v;
if(d[u]+edge3[k].w<=d[v]){
d[v]=d[u]+edge3[k].w;
if(!vis3[v]){
vis3[v]=true;
pq.push(v);
}
}
}
}
}
int main(){
init();
spfa1(n,dist1);
spfa2(n,dist2);
for(int i=1;i<=n;i++){
for(int k=first3[i];k;k=edge3[k].next){
int u=edge3[k].v;
if(dist1[i]+edge1[k].w!=dist1[u])edge3[k].w++;
if(dist2[i]+edge2[k].w!=dist2[u])edge3[k].w++;
}
}
spfa3(n,dist3);
printf("%d\n",dist3[1]);
return 0;
}