zoukankan      html  css  js  c++  java
  • [CF1321D]Navigation System

    【原题】

    The map of Bertown can be represented as a set of nn intersections, numbered from 11 to nn and connected by mm one-way roads. It is possible to move along the roads from any intersection to any other intersection. The length of some path from one intersection to another is the number of roads that one has to traverse along the path. The shortest path from one intersection vv to another intersection uu is the path that starts in vv, ends in uu and has the minimum length among all such paths.

    Polycarp lives near the intersection ss and works in a building near the intersection tt. Every day he gets from ss to tt by car. Today he has chosen the following path to his workplace: p1p1, p2p2, ..., pkpk, where p1=sp1=s, pk=tpk=t, and all other elements of this sequence are the intermediate intersections, listed in the order Polycarp arrived at them. Polycarp never arrived at the same intersection twice, so all elements of this sequence are pairwise distinct. Note that you know Polycarp's path beforehand (it is fixed), and it is not necessarily one of the shortest paths from ss to tt.

    Polycarp's car has a complex navigation system installed in it. Let's describe how it works. When Polycarp starts his journey at the intersection ss, the system chooses some shortest path from ss to tt and shows it to Polycarp. Let's denote the next intersection in the chosen path as vv. If Polycarp chooses to drive along the road from ss to vv, then the navigator shows him the same shortest path (obviously, starting from vv as soon as he arrives at this intersection). However, if Polycarp chooses to drive to another intersection ww instead, the navigator rebuilds the path: as soon as Polycarp arrives at ww, the navigation system chooses some shortest path from ww to tt and shows it to Polycarp. The same process continues until Polycarp arrives at tt: if Polycarp moves along the road recommended by the system, it maintains the shortest path it has already built; but if Polycarp chooses some other path, the system rebuilds the path by the same rules.

    Here is an example. Suppose the map of Bertown looks as follows, and Polycarp drives along the path [1,2,3,4][1,2,3,4] (s=1s=1, t=4t=4):

    Check the picture by the link http://tk.codeforces.com/a.png

    1. When Polycarp starts at 11, the system chooses some shortest path from 11 to 44. There is only one such path, it is [1,5,4][1,5,4];
    2. Polycarp chooses to drive to 22, which is not along the path chosen by the system. When Polycarp arrives at 22, the navigator rebuilds the path by choosing some shortest path from 22 to 44, for example, [2,6,4][2,6,4] (note that it could choose [2,3,4][2,3,4]);
    3. Polycarp chooses to drive to 33, which is not along the path chosen by the system. When Polycarp arrives at 33, the navigator rebuilds the path by choosing the only shortest path from 33 to 44, which is [3,4][3,4];
    4. Polycarp arrives at 44 along the road chosen by the navigator, so the system does not have to rebuild anything.

    Overall, we get 22 rebuilds in this scenario. Note that if the system chose [2,3,4][2,3,4] instead of [2,6,4][2,6,4] during the second step, there would be only 11 rebuild (since Polycarp goes along the path, so the system maintains the path [3,4][3,4] during the third step).

    The example shows us that the number of rebuilds can differ even if the map of Bertown and the path chosen by Polycarp stays the same. Given this information (the map and Polycarp's path), can you determine the minimum and the maximum number of rebuilds that could have happened during the journey?

    Input

    The first line contains two integers nn and mm (2nm21052≤n≤m≤2⋅105) — the number of intersections and one-way roads in Bertown, respectively.

    Then mm lines follow, each describing a road. Each line contains two integers uu and vv (1u,vn1≤u,v≤n, uvu≠v) denoting a road from intersection uu to intersection vv. All roads in Bertown are pairwise distinct, which means that each ordered pair (u,v)(u,v) appears at most once in these mm lines (but if there is a road (u,v)(u,v), the road (v,u)(v,u) can also appear).

    The following line contains one integer kk (2kn2≤k≤n) — the number of intersections in Polycarp's path from home to his workplace.

    The last line contains kk integers p1p1, p2p2, ..., pkpk (1pin1≤pi≤n, all these integers are pairwise distinct) — the intersections along Polycarp's path in the order he arrived at them. p1p1 is the intersection where Polycarp lives (s=p1s=p1), and pkpk is the intersection where Polycarp's workplace is situated (t=pkt=pk). It is guaranteed that for every i[1,k1]i∈[1,k−1] the road from pipi to pi+1pi+1 exists, so the path goes along the roads of Bertown.

    Output

    Print two integers: the minimum and the maximum number of rebuilds that could have happened during the journey.

    Examples
    input
    Copy
    6 9
    1 5
    5 4
    1 2
    2 3
    3 4
    4 1
    2 6
    6 4
    4 2
    4
    1 2 3 4
    
    output
    Copy
    1 2
    
    input
    Copy
    7 7
    1 2
    2 3
    3 4
    4 5
    5 6
    6 7
    7 1
    7
    1 2 3 4 5 6 7
    
    output
    Copy
    0 0
    
    input
    Copy
    8 13
    8 7
    8 6
    7 5
    7 4
    6 5
    6 4
    5 3
    5 2
    4 3
    4 2
    3 1
    2 1
    1 8
    5
    8 7 5 2 1
    
    output
    Copy
    0 3
    



    【思路】

    最短路,pre[i]记录每个结点的前驱结点。如果下一结点是当前结点的前驱结点并且当前结点的前驱结点个数>1,最大重驱次数++。如果下一结点是当前结点的前驱结点并且当前结点的前驱结点个数 == 1, 那么无法进行重驱。如果下一结点不是当前结点的前驱结点,最大、最小重驱次数++。

    (之前用num数组存当前点最短路个数,爆LL了)

      1 #include <algorithm>
      2 #include <cmath>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <list>
      6 #include <map>
      7 #include <iostream>
      8 #include <queue>
      9 #include <set>
     10 #include <stack>
     11 #include <string>
     12 #include <vector>
     13 #include <iomanip>
     14 #define LL long long
     15 #define inf 0x3f3f3f3f 
     16 #define INF 0x3f3f3f3f3f3f
     17 #define PI 3.1415926535898
     18 #define F first
     19 #define S second
     20 #define lson  rt << 1
     21 #define rson  rt << 1 | 1
     22 using namespace std;
     23 
     24 const int maxn = 2e5 + 7;
     25 const int maxm = 4e5 + 7;
     26 int n, m;
     27 string s;
     28 vector<int> v, pre[maxn];
     29 map < pair<int, int>, int > mp;
     30 struct pp
     31 {
     32     int v, w, next;
     33 }edge[maxn];
     34 int head[maxn], dis[maxn], vis[maxn], path[maxn], cnt = 0;
     35 struct node
     36 {
     37     int u, dis;
     38     bool operator < (const node& a) const
     39     {
     40         return a.dis < dis;
     41     }
     42 };
     43 void add(int t1, int t2, int t3)
     44 {
     45     edge[++cnt].v = t2;
     46     edge[cnt].w = t3;
     47     edge[cnt].next = head[t1];
     48     head[t1] = cnt;
     49 }
     50 void dijkstra(int b)
     51 {
     52     priority_queue<node> que;
     53     int i;
     54     memset(dis, inf, sizeof(dis));
     55     memset(vis, 0, sizeof(vis));
     56     dis[b] = 0;
     57     node  temp;
     58     temp.u = b; temp.dis = 0;
     59     que.push(temp);
     60     while (!que.empty())
     61     {
     62         int u = que.top().u;
     63         que.pop();
     64         if (vis[u]) continue;
     65         vis[u] = 1;
     66         for (i = head[u]; i; i = edge[i].next)
     67         {
     68             int v = edge[i].v;
     69             if (vis[v]) continue;
     70             if (dis[v] == dis[u] + edge[i].w)
     71             {
     72                 pre[v].push_back(u);
     73             }
     74             if (dis[v] > dis[u] + edge[i].w)
     75             {
     76                 dis[v] = dis[u] + edge[i].w;
     77                 temp.u = v; temp.dis = dis[v];
     78                 que.push(temp);
     79                 pre[v].clear();
     80                 pre[v].push_back(u);
     81             }
     82         }
     83     }
     84 }
     85 
     86 int main()
     87 {
     88     ios::sync_with_stdio(false);
     89     cin.tie(0);
     90     cin >> n >> m;
     91     int ta, tb;
     92     for (int i = 1; i <= m; i++)
     93     {
     94         cin >> ta >> tb;
     95         add(tb, ta, 1);
     96         mp[{ta, tb}] = cnt;
     97     }
     98     int k;
     99     cin >> k;
    100     for (int i = 1; i <= k; i++)
    101     {
    102         cin >> path[i];
    103     }
    104     dijkstra(path[k]);
    105     int mn = 0, mx = 0;
    106     for (int i = 1; i <= k - 1; i++)
    107     {
    108         if (pre[path[i]].size() > 1 && dis[path[i]] - dis[path[i + 1]] == edge[mp[{ path[i], path[i + 1] }]].w)
    109         {
    110             mx++;
    111         }
    112         else if(dis[path[i]] - dis[path[i + 1]] != edge[mp[{ path[i], path[i + 1] }]].w)
    113         {
    114             mn++;
    115             mx++;
    116         }
    117     }
    118     cout << mn << " " << mx << endl;
    119 
    120 }
  • 相关阅读:
    反射的基础详解
    数组,排序,枚举
    继承,多态,抽象,接口
    视图层 view
    常用类Object,String类详解
    模板层 Template
    自定义注解
    Django 高级
    常用类Math,StringBuffer,包装类,Date
    内部类,异常
  • 原文地址:https://www.cnblogs.com/hfcdyp/p/13370172.html
Copyright © 2011-2022 走看看