Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round) D. 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
 
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
 
1 2
Input
 
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
 
0 0
Input
 
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
 
0 3
作为算法萌新菜鸡做这种图论题属实难顶,各种炸细节...题意大概是给定一个有向图,给定这个人从s到t的路线,导航总是显示当前点到终点的最短路,如果这个人没按照导航走的话导航路线就要重建,问这个人如果一直按照最开始的路线走,导航最多重建几次,最少重建几次。
既然一定要沿着给定的路走,就沿着它一个节点一个节点分析,维护最少重建次数和最多重建次数两个变量。假设当走到i节点时,如果这个节点到终点最短路长度等于给定路径第i+1个节点到终点的最短路长度+1,那么说明第i+1个节点的最短路包含在了第i个节点的最短路之内,这说明此时最少重建次数一定不用更新(相当于这一段是按照导航走的,同时也和原路线重合),最大重建次数是否更新取决于第i个节点是否有另一条通往终点的最短路,有的话则自增1;如果
节点i到终点最短路长度不等于第i+1个节点到终点的最短路长度+1,这时候导航一定会重建最短路,要同时更新两个变量。可以看样例方便理解。具体处理的话,可以建反图,跑Dijkstra求终点到各个点的最短路,然后遍历给定路线节点依次判断。
#include <bits/stdc++.h>
using namespace std;
const int N=200005,M=200005;
int head[N],ver[M],edge[M],Next[M],d[N];//反图
int head1[N],ver1[M],edge1[M],Next1[M],d1[N]; //正图 
bool v[N];
int n,m,tot=0,tot1=0;
priority_queue< pair<int,int> >q;
int rou[200005],k;
void add(int x,int y, int z)
{
    ver[++tot]=y;
    edge[tot]=z;
    Next[tot]=head[x];
    head[x]=tot;
}
void add1(int x,int y,int z)
{
    ver1[++tot1]=y;
    edge1[tot1]=z;
    Next1[tot1]=head1[x];
    head1[x]=tot1;
}
void dijkstra()
{
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    memset(cnt,0,sizeof(cnt)); 
    d[rou[k]]=0;
    q.push(make_pair(0,rou[k]));
    cnt[rou[k]]=1;//!!!!!!自己到自己的最短路条数为1 
    while(q.size())
    {
        int x=q.top().second;q.pop();
        if(v[x])continue;
        v[x]=1;
        int i;
        for(i=head[x];i;i=Next[i])
        {
            int y=ver[i],z=edge[i];
            if(d[y]>d[x]+z)
            {
                d[y]=d[x]+z;
                q.push(make_pair(-d[y],y));
            }
        }
    }
}
int main()
{
    int n,m;
    cin>>n>>m;
    int i,j;
    for(i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(y,x,1);//建反图 
        add1(x,y,1);//正常图 
    }
    cin>>k;
    for(i=1;i<=k;i++)scanf("%d",&rou[i]);
    dijkstra();
    int mmin=0,mmax=0; 
    for(i=1;i<=k-1;i++)
    {
        if(d[rou[i]]==d[rou[i+1]]+1)//相等 
        {
            int p;
            for(p=head1[rou[i]];p;p=Next1[p])//遍历起点为rou[i]的单向路 (用存的反图搜,应该用正图搜 
            {
                int nxt=ver1[p];//rou[i]的下一个节点 
                if(d[rou[i]]==d[nxt]+1&&nxt!=rou[i+1])//存在第二条最短路的话 
                {
                    mmax++;
                    break;
                }
            }
        }
        else
        {
            mmax++;
            mmin++;            
        }
    }
    cout<<mmin<<' '<<mmax;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lipoicyclic/p/12405518.html