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 (2 <= N <= 10,000) and M directional roads (1 <= M <= 50,000). Road i connects intersections A_i (1 <= A_i <= N) and B_i (1 <= B_i <= N). 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 P_i units of time to traverse according to the first GPS unit, and Q_i units of time to traverse according to the second unit (each travel time is an integer in the range 1..100,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.

输入:
Line 1: The integers N and M.
Line i describes road i with four integers: A_i B_i P_i Q_i.

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

题目大意:
给你一个N个点的有向图,可能有重边.有两个GPS定位系统,分别认为经过边i的时间为Pi,和Qi.每走一条边的时候,如果一个系统认为走的这条边不是它认为的最短路,就会受到警告一次T T两个系统是分开警告的,就是说当走的这条边都不在两个系统认为的最短路范围内,就会受到2次警告.如果边(u,v)不在u到n的最短路径上,这条边就受到一次警告。求从1到n最少受到多少次警告。

解题思路:
第一次看就断定是一个图论,然后果断跑了一个SPFA,然后就死了,仔细思考后发现需要重新建图,且第一次建图时需要反向建边,第二次建图利用原来第一次跑SPFA记录的两个GPS的最优路线正向建图,再跑一个SPFA就好。

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#include<cstdio>
using namespace std;
#define INF 0x7fffffff
#define N 50010
struct Edge{
    int from,to;int p,q,w;//p,q为两个导航图的权值 w为警告次数
    Edge(int from,int to,int p,int q,int w):from(from),to(to),p(p),q(q),w(w){}
};
vector<Edge> e[N],e_next[N];//边目录配合邻接表储存原始图和二次建图
int fa_p[N],fa_q[N];//对于每个导航的最短路径
int P[N],Q[N],u[N],v[N];//记录每条边的信息
int dis_p[N],dis_q[N],dis[N],vis[N];
int n,m,last=1,ans=INF;
void SPFA_first(int start);
void SPFA_next(int start);
void build_first();
void build_next();
int main(){
    scanf("%d%d",&n,&m);
    build_first();
    SPFA_first(n);//第一次从n跑
    build_next();
    SPFA_next(1);
    printf("%d",dis[n]);
    return 0;
}
void SPFA_first(int start){
    memset(dis_p,127,sizeof(dis_p));
    memset(dis_q,127,sizeof(dis_q));
    memset(vis,0,sizeof(vis));
    dis_p[start]=dis_q[start]=0;vis[start]=1;
    queue<int> c;
    c.push(start);
    while(!c.empty()){
        int o=c.front();c.pop();
        vis[o]=0;
        int se=e[o].size();
        for(int i=0;i<se;i++){
            Edge ne=e[o][i];
            int x=ne.from,y=ne.to,p=ne.p,q=ne.q;
            if(dis_p[y]>dis_p[x]+p){//P导航的最短路
                dis_p[y]=dis_p[x]+p;
                fa_p[y]=x;//记录路径
                if(!vis[y]){vis[y]=1;c.push(y);}
            }
            if(dis_q[y]>dis_q[x]+q){//Q导航的最短路
                dis_q[y]=dis_q[x]+q;
                fa_q[y]=x;
                if(!vis[y]){vis[y]=1;c.push(y);}
            }
        }
    }
}
void SPFA_next(int start){
    memset(dis,127,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[start]=0;vis[start]=1;
    queue<int> c;
    c.push(start);
    while(!c.empty()){
        int o=c.front();c.pop();
        vis[o]=0;
        int se=e_next[o].size();
        for(int i=0;i<se;i++){
            int x=e_next[o][i].from;
            int y=e_next[o][i].to;
            int w=e_next[o][i].w;
            if(dis[y]>dis[x]+w){//松弛受警告的次数
                dis[y]=dis[x]+w;
                if(!vis[y]){vis[y]=1;c.push(y);}
            }
        }
    }
}
void build_first(){
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&u[i],&v[i],&P[i],&Q[i]);
        e[v[i]].push_back(Edge(v[i],u[i],P[i],Q[i],0));
        //反向建边
    }
}
void build_next(){//原来的图反向建边,重新建图变为正向边
    for(int i=1;i<=n;i++){//重新正向建图,以警告数为权值
        int se=e[i].size();
        for(int j=0;j<se;j++){
            int from_new=e[i][j].to;
            int p_new=e[i][j].p;
            int q_new=e[i][j].q;
            int w=0;//判断是否在GPS最短路中
            if(fa_p[from_new]!=to_new)w++;
            if(fa_q[from_new]!=to_new)w++;                         e_next[from_new].push_back(Edge(from_new,to_new,p_new,q_new,w));
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值