Processing math: 100%

Luogu P3106 [USACO14OPEN]GPS的决斗Dueling GPS's(最短路)

P3106 [USACO14OPEN]GPS的决斗Dueling GPS's

题意

题目描述

Farmer John has recently purchased a new car online, but in his haste he accidentally clicked the "Submit" button twice when selecting extra features for the car, and as a result the car ended up equipped with two GPS navigation systems! Even worse, the two systems often make conflicting decisions about the route that FJ should take.

The map of the region in which FJ lives consists of N intersections (2N10,000) and M directional roads (1M50,000). Road i connects intersections Ai(1AiN) and Bi(1BiN). Multiple roads could connect the same pair of intersections, and a bi-directional road (one permitting two-way travel) is represented by two separate directional roads in opposite orientations. FJ's house is located at intersection 1, and his farm is located at intersection N. It is possible to reach the farm from his house by traveling along a series of directional roads.

Both GPS units are using the same underlying map as described above; however, they have different notions for the travel time along each road. Road i takes Pi units of time to traverse according to the first GPS unit, and Qi units of time to traverse according to the second unit (each travel time is an integer in the range 1100,000).

FJ wants to travel from his house to the farm. However, each GPS unit complains loudly any time FJ follows a road (say, from intersection X to intersection Y) that the GPS unit believes not to be part of a shortest route from X to the farm (it is even possible that both GPS units can complain, if FJ takes a road that neither unit likes).

Please help FJ determine the minimum possible number of total complaints he can receive if he chooses his route appropriately. If both GPS units complain when FJ follows a road, this counts as +2 towards the total.

给你一个N个点的有向图,可能有重边.

有两个GPS定位系统,分别认为经过边i的时间为PiQi.

每走一条边的时候,如果一个系统认为走的这条边不是它认为的最短路,就会受到警告一次T

两个系统是分开警告的,就是说当走的这条边都不在两个系统认为的最短路范围内,就会受到2次警告.

如果边(u,v)不在un的最短路径上,这条边就受到一次警告,求从1n最少受到多少次警告。

输入输出格式

输入格式:

Line 1: The integers N and M.

Line i describes road i with four integers: Ai Bi Pi Qi.

输出格式:

Line 1: The minimum total number of complaints FJ can receive if he routes himself from his house to the farm optimally.

输入输出样例

输入样例:

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

说明

There are 5 intersections and 7 directional roads. The first road connects from intersection 3 to intersection 4; the first GPS thinks this road takes 7 units of time to traverse, and the second GPS thinks it takes 1 unit of time, etc.

If FJ follows the path 1 -> 2 -> 4 -> 5, then the first GPS complains on the 1 -> 2 road (it would prefer the 1 -> 3 road instead). However, for the rest of the route 2 -> 4 -> 5, both GPSs are happy, since this is a shortest route from 2 to 5 according to each GPS.

思路

太fAKe了。 --Mercury

我们发现,无论走到哪个点,GPS的警告都是使用到终点n的最短路径来判断的,所以我们先预处理出两台GPS到终点n的最短路长度dis1,dis2,这可以用反向跑最短路来实现。然后对于一条边(u,v),如果dis1[u]+len1(u,v)==dis1[v],那么第一台GPS是不会警告的;同样,如果dis2[u]+len2(u,v)==dis2[v],那么第二台GPS是不会警告的。那么我们以此来改变每条边的边权为GPS警告的次数,然后再跑一遍最短路,就可以得到答案了。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=1e4+5;
const LL MAXM=5e4+5;
LL n,m,dis[MAXN],dis1[MAXN],dis2[MAXN];
LL cnt,top[MAXN],to[MAXM],len[MAXM],nex[MAXM];
LL cnt1,top1[MAXN],to1[MAXM],len1[MAXM],nex1[MAXM];
LL cnt2,top2[MAXN],to2[MAXM],len2[MAXM],nex2[MAXM];
bool vis[MAXN];
inline LL read()
{
    LL re=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
    return re;
}
inline void add_edge(LL x,LL y,LL z){to[++cnt]=y,len[cnt]=z,nex[cnt]=top[x],top[x]=cnt;}
inline void add_edge1(LL x,LL y,LL z){to1[++cnt1]=y,len1[cnt1]=z,nex1[cnt1]=top1[x],top1[x]=cnt1;}
inline void add_edge2(LL x,LL y,LL z){to2[++cnt2]=y,len2[cnt2]=z,nex2[cnt2]=top2[x],top2[x]=cnt2;}
void SPFA()
{
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    queue<LL>Q;
    Q.push(1);
    while(!Q.empty())
    {
        LL now=Q.front();Q.pop();
        vis[now]=false;
        for(int i=top[now];i;i=nex[i])
            if(dis[to[i]]>dis[now]+len[i])
            {
                dis[to[i]]=dis[now]+len[i];
                if(!vis[to[i]])
                {
                    vis[to[i]]=true;
                    Q.push(to[i]);
                }
            }
    }
}
void SPFA1()
{
    memset(dis1,0x3f,sizeof dis1);
    dis1[n]=0;
    queue<LL>Q;
    Q.push(n);
    while(!Q.empty())
    {
        LL now=Q.front();Q.pop();
        vis[now]=false;
        for(int i=top1[now];i;i=nex1[i])
            if(dis1[to1[i]]>dis1[now]+len1[i])
            {
                dis1[to1[i]]=dis1[now]+len1[i];
                if(!vis[to1[i]])
                {
                    vis[to1[i]]=true;
                    Q.push(to1[i]);
                }
            }
    }
}
void SPFA2()
{
    memset(dis2,0x3f,sizeof dis2);
    dis2[n]=0;
    queue<LL>Q;
    Q.push(n);
    while(!Q.empty())
    {
        LL now=Q.front();Q.pop();
        vis[now]=false;
        for(int i=top2[now];i;i=nex2[i])
            if(dis2[to2[i]]>dis2[now]+len2[i])
            {
                dis2[to2[i]]=dis2[now]+len2[i];
                if(!vis[to2[i]])
                {
                    vis[to2[i]]=true;
                    Q.push(to2[i]);
                }
            }
    }
}
int main()
{
    n=read(),m=read();
    while(m--)
    {
        int x=read(),y=read(),z1=read(),z2=read();
        add_edge1(y,x,z1);
        add_edge2(y,x,z2);
    }
    SPFA1(),SPFA2();
    for(int i=1;i<=n;i++)
        for(int j=top1[i];j;j=nex1[j])
        {
            int l=2;
            if(dis1[to1[j]]==dis1[i]+len1[j]) l--;
            if(dis2[to2[j]]==dis2[i]+len2[j]) l--;
            add_edge(to1[j],i,l);
        }
    SPFA();
    printf("%lld",dis[n]);
    return 0;
}
posted @   UranusITS  阅读(137)  评论(0)    收藏  举报
编辑推荐:
· 运维排查 | SaltStack 远程命令执行中文乱码问题
· Java线程池详解:高效并发编程的核心利器
· 从“看懂世界”到“改造世界”:AI发展的四个阶段你了解了吗?
· 协程本质是函数加状态机——零基础深入浅出 C++20 协程
· 编码之道,道心破碎。
阅读排行:
· 基于.net6的一款开源的低代码、权限、工作流、动态接口平台
· 一个自认为理想主义者的程序员,写了5年公众号、博客的初衷
· Claude Code 初体验 - Windows
· 基于 C# 编写的轻量级工控网关和 SCADA 组态软件
· 纯C#软实现openGL(V0.1),黑盒变白盒
点击右上角即可分享
微信分享提示