zoukankan      html  css  js  c++  java
  • [BZOJ3538]坑爹的GPS

    题目描述 Description###

    有一天,(FJ) 买了一辆车,但是,他一手下载了两个(GPS) 系统。好了现在麻烦的事情来了,(GPS) 有一个功能大概大家也知道,如果(FJ) 没有按照(GPS) 内置地图的最短路走,(GPS) 就会报错来骚扰你。现在(FJ) 准备从他的农舍(在1这个点)开车到他的谷屋((n) 这个点)。(FJ) 给了你两个(GPS) 系统内置地图的信息,他想知道,他最少会听到多少次报错(如果(FJ) 走的路同时不满足两个(GPS) ,报错次数+2)

    输入描述 Input Description###

    第一行:(n) ,(k)(n) 表示有(FJ) 的谷屋在哪,同时保证(GPS) 内置地图里的点没有超过(n) 的点。(K) 表示(GPS) 内置地图里的路有多少条,如果两个点没有连接则表明这不是一条通路。
    接下来(k) 行,每行4个数(X) ,(Y) ,(A) ,(B) 分别表示从(X)(Y) 在第一个(GPS) 地图里的距离是(A) ,在第二个(GPS) 地图里的是(B) 。注意由于地形的其他因素(GPS) 给出的边是有向边。

    输出描述 Output Description###

    一个值,表示(FJ) 最少听到的报错次数。

    样例输入 Sample Input###

    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
    

    样例输出 Sample Output###

    1
    

    数据范围及提示 Data Size & Hint###

    (FJ) 选择的路线是1 2 4 5,但是(GPS) 1认为的最短路是1到3,所以报错一次,对于剩下的2 4 5,两个(GPS) 都不会报错。
    (N<=10000) ,至于路有多少条自己算吧。数据保证所有的距离都在$2^{31}-1 $ 以内。

    之前的一些废话###

    离期中还有两周,离NOIP还有不到三周,下午开始停课计划,是时候拼了!

    题解###

    对于第一个(GPS) 求一遍最短路,对第二个也求一遍最短路,注意是以(n) 为源点进行最短路,所以还要存一个反图。然后我们尝试建一个报错的地图。在原图上搜索,对于一条边,如果走这一条边不满足第一个(GPS) 上的最短路这条路边权加一,同理判断是否第二个的(GPS) ,建好图之后再跑一个最短路即可。

    代码###

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> PII;
    #define mem(a,b) memset(a,b,sizeof(a))
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    const int maxn=10010,maxm=50010;
    struct Edge
    {
    	int u,v,w1,w2,next;
    	Edge() {}
    	Edge(int _1,int _2,int _3,int _4,int _5):u(_1),v(_2),w1(_3),w2(_4),next(_5) {}
    }e[maxm<<1],rev[maxm<<1],E[maxm<<1];
    int n,m,first[maxn],rfirst[maxn],First[maxn],c1=-1,c2=-1,ce=-1,a,b,c,d,dis1[maxn],dis2[maxn],dis3[maxn];
    bool vis[maxn];
    queue<int> Q;
    void addEdge(int a,int b,int c,int d)
    {
    	e[++c1]=Edge(a,b,c,d,first[a]);first[a]=c1;
    	rev[++c2]=Edge(b,a,c,d,rfirst[b]);rfirst[b]=c2;
    }
    void AddEdge(int a,int b,int c){E[++ce]=Edge(a,b,c,0,First[a]);First[a]=ce;}
    void SPFA1()
    {
    	mem(vis,0);mem(dis1,42);
    	while(Q.size())Q.pop();
    	Q.push(n);vis[n]=1;dis1[n]=0;
    	while(Q.size())
    	{
    		int now=Q.front();Q.pop();
    		for(int i=rfirst[now];i!=-1;i=rev[i].next)
    		    if(dis1[now]+rev[i].w1<dis1[rev[i].v])
    		    {
    		    	dis1[rev[i].v]=dis1[now]+rev[i].w1;
    		    	if(!vis[rev[i].v])
    				{
    					Q.push(rev[i].v);
    					vis[rev[i].v]=1;
    				} 
    			}
    		vis[now]=0;
    	}
    	return;
    }
    void SPFA2()
    {
    	mem(vis,0);mem(dis2,42);
    	while(Q.size())Q.pop();
    	Q.push(n);vis[n]=1;dis2[n]=0;
    	while(Q.size())
    	{
    		int now=Q.front();Q.pop();
    		for(int i=rfirst[now];i!=-1;i=rev[i].next)
    		    if(dis2[now]+rev[i].w2<dis2[rev[i].v])
    		    {
    		    	dis2[rev[i].v]=dis2[now]+rev[i].w2;
    		    	if(!vis[rev[i].v])
    				{
    					Q.push(rev[i].v);
    					vis[rev[i].v]=1;
    				} 
    			}
    		vis[now]=0;
    	}
    	return;
    }
    void SPFA3()
    {
    	mem(vis,0);mem(dis3,42);
    	while(Q.size())Q.pop();
    	Q.push(1);vis[1]=1;dis3[1]=0;
    	while(Q.size())
    	{
    		int now=Q.front();Q.pop();
    		for(int i=First[now];i!=-1;i=E[i].next)
    		    if(dis3[now]+E[i].w1<dis3[E[i].v])
    		    {
    		    	dis3[E[i].v]=dis3[now]+E[i].w1;
    		    	if(!vis[E[i].v])
    				{
    					Q.push(E[i].v);
    					vis[E[i].v]=1;
    				} 
    			}
    		vis[now]=0;
    	}
    	return;
    }
    int main()
    {
    	mem(first,-1);mem(rfirst,-1);mem(First,-1);
    	n=read();m=read();
    	for(int i=1;i<=m;i++)a=read(),b=read(),c=read(),d=read(),addEdge(a,b,c,d);
    	SPFA1();SPFA2();
    	for(int point=1;point<=n;point++)
    		for(int i=first[point];i!=-1;i=e[i].next)
    		{
    			int cnt=0;
    			if(dis1[point]!=dis1[e[i].v]+e[i].w1)cnt++;
    			if(dis2[point]!=dis2[e[i].v]+e[i].w2)cnt++;
    			AddEdge(point,e[i].v,cnt);
    		}
    	SPFA3();
    	printf("%d
    ",dis3[n]);
    	return 0;
    }
    
    

    总结###

    还是比较套路的。

  • 相关阅读:
    javascript之数组操作
    python中的类中属性元素加self.和不加self.的区别
    Q查询
    jQuery EasyUI的各历史版本和应用
    了解Entity Framework中事务处理
    C#中Abstract和Virtual的区别
    控制器post参数接收
    存储过程调用存储过程
    表变量、临时表(with as ,create table)
    LINQ TO SQL 实现无限递归查询
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/7719041.html
Copyright © 2011-2022 走看看