USACO2014 Open Silver Dueling GPSs


Description

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(2N 10,000) and M directional roads (1M 50,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 [1,105] ).

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個結點,M條邊的有向圖,每條邊分別有兩個權值表示GPS1和GPS2的估價距離。求出最少有多少次,FJ會違背GPS所指定的下一條最優路線。如果FJ本次選擇的路線與兩個GPS都不相同,則次數+2。

Input

Line 1: The integers N and M.
Line i describes road i with four integers: Ai ,Bi ,Pi ,Qi .

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

Output

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

Sample Output

1

Output Details

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.
大意:走1->2->4->5這條路線,只會有一次違背。


Solution
注意給出的圖是有向圖,因爲這個被坑了好久……

考慮GPS的工作方式:它給出的是當前的點到終點的最短距離路徑,而與之前經過的路徑無關。如果離開了原先設定的最短路,它會重新以該點爲起點找一條最短路(甚至回跑到原先經過的點)。即到了一個點就找一次最短路。但如果正着找一遍這個點到所有點的最短路,就有很多不必要的點被更新了。

那麼我們只需要根據兩種權值各自跑一遍從終點n開始的Dijkstra,得到每個點到終點的最短路徑。之後再判斷某條邊是否在某段最短路徑上,如果不是,接下來選這條邊總違反次數就會增加。

那麼根據以上操作,所有的邊都會重新得到一個在0~2之間的權值,再將所有邊反向,然後跑一下從1到n的最短路即可。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define M 100005
using namespace std;
inline void Rd(int &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do res=(res<<3)+(res<<1)+(c^48);
    while(c=getchar(),c>47);
}
struct node{int to,val;};
vector<node>G[3][M];
int dis[3][M];
int n,m;
bool vis[M];
void Put_edge(int u,int v,int w,int flag){
    G[flag][u].push_back((node){v,w});
}
struct Node{
    int u,dis;
    bool operator <(const Node &cmp)const{return dis>cmp.dis;}
};
void Dijkstra(int st,int f){
    priority_queue<Node>Q;
    memset(dis[f],-1,sizeof(dis[f]));
    memset(vis,0,sizeof(vis));

    dis[f][st]=0;Q.push((Node){st,dis[f][st]});
    while(!Q.empty()){
        Node now=Q.top();Q.pop();
        if(vis[now.u])continue;
        vis[now.u]=true;
        for(int j=0;j<(int)G[f][now.u].size();j++){
            int v=G[f][now.u][j].to,w=G[f][now.u][j].val;
            if(vis[v])continue;
            if(dis[f][v]==-1||dis[f][v]>dis[f][now.u]+w){
                dis[f][v]=dis[f][now.u]+w;
                Q.push((Node){v,dis[f][v]});
            }
        }
    }
}
int main(){
    Rd(n),Rd(m);
    for(int i=1;i<=m;i++){
        int u,v,w0,w1;
        Rd(u),Rd(v),Rd(w0),Rd(w1);
        Put_edge(v,u,w0,0);//將邊反向 
        Put_edge(v,u,w1,1);
    }
    Dijkstra(n,0);
    Dijkstra(n,1);
    for(int u=1;u<=n;u++)
        for(int j=0;j<(int)G[0][u].size();j++){
            int v=G[0][u][j].to;
            int cnt=0;
            cnt+=(dis[0][v]!=dis[0][u]+G[0][u][j].val);
            cnt+=(dis[1][v]!=dis[1][u]+G[1][u][j].val);
            Put_edge(v,u,cnt,2);//再次反向 
        }
    Dijkstra(1,2);
    printf("%d\n",dis[2][n]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章