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;
}
posted @ 2018-11-30 16:53  虚拟北方virtual_north。  阅读(119)  评论(0编辑  收藏  举报