题目链接:https://codeforces.ml/contest/1321/problem/D
题意:给你n个点,m条无向边,以及一条含n个点得路线。就像地图导航系统,每次在最短路出错就要重新导航,问最小得导航次数和最大得导航次数(最短路可能有多条)。
思路:反向建边。之后用bfs找出终点a[k]到每个点得最短路。那样我们扫描整个路径,如果dis[a[i]] != dis[a[i+1]] + 1,就说明最短路导航出错,需要重新导航,所以ans1++ , ans2++。反之,如果相等,那就考虑有没有其他的最短路,有的话ans2++。那该如何处理呢?这里我直接用bfs求解最短路,在求解最短路得过程中就可以直接处理出那个有多少条最短路。如何实现呢?就是
dis[v] == dis[u] + 1 && dis[v] != -1(说明v这个点先前已经扫描过啦,而这里又出现了一条最短路相同的点,那不就说明v到终点的最短路不止一条嘛!!!)
AC代码如下:
#include <set>
#include <map>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define fast_io ios::sync_with_stdio(false)
const int maxn = 2e5 + 7;
const int INF = 0x3f3f3f3f;
int head[maxn];
struct Edge {
int to,next;
}edge[maxn];
int tot;
void init() {
memset(head,-1,sizeof(head));
tot = 0;
}
void addedge(int u,int v) {
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
int dis[maxn],in[maxn];
queue<int>q;
void bfs(int x) {
memset(dis,-1,sizeof(dis));
dis[x] = 0 , in[x] = 0;
while(!q.empty()) q.pop();
q.push(x);
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i = head[u] ; i != -1 ; i = edge[i].next) {
int v = edge[i].to;
if(dis[v] == -1) {
dis[v] = dis[u] + 1;
q.push(v);
in[v] = 1;
} else if(dis[v] == dis[u] + 1) {
//为了简单一点,有多条最短路in[v]就为2,否则就为1
in[v] = 2;
}
}
}
}
int a[maxn];
int main() {
fast_io;
int n,m;
cin >> n >> m;
init();
for(int i = 1 ; i <= m ; i++) {
int u,v;
cin >> u >> v;
addedge(v,u);
}
int k;
cin >> k;
for(int i = 1 ; i <= k ; i++) {
cin >> a[i];
}
bfs(a[k]);
int ans1 = 0 , ans2 = 0;
for(int i = 1 ; i <= k ; i++) {
if(dis[a[i]] != dis[a[i+1]] + 1) {
ans1++ , ans2++;
} else {
if(in[a[i]] == 2) {
ans2++;
}
}
}
cout << ans1 << " " << ans2 << endl;
return 0;
}