Codeforces 1321D Navigation System
题意:给你一张图和一条路径,沿着这条路径走,若走到某个点,该点不是之前的点算的最短路径上的一个点,就需要重新计算,求重新计算的最大次数与最小次数
已知终点,那我们可以反向跑一个最短路,求出每个点到终点\(t\)的距离\(d_u\), 假设现在是\(u\)点
1.若\(u\)全部的可达点v满足 \(d_u > d_v + 1\), 则该点必须重新计算
2.若\(u\)的可达点至少有一点v满足 \(d_u = d_v + 1\), 且该点\(v\)不是题目给定的\(u\)点的下一点路径, 则最大次数+1
#include<bits/stdc++.h>
using namespace std;
#define ms(x,y) memset(x, y, sizeof(x))
#define lowbit(x) ((x)&(-x))
typedef long long LL;
typedef pair<int,int> pii;
const int maxn = 2e5+5;
int x[maxn], y[maxn], dis[maxn];
vector<int> G[maxn];
bool vis[maxn];
void dijkstra(int s) {
ms(dis, 63), dis[s] = 0;
priority_queue<pii> q;
q.push(make_pair(0, s));
while(!q.empty()) {
auto u = q.top().second; q.pop();
if(vis[u]) continue;
vis[u] = true;
for(auto v: G[u]) {
if(dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
q.push(make_pair(-dis[v], v));
}
}
}
}
void run_case() {
int n, m;
cin >> n >> m;
for(int i = 0; i < m; ++i) {
int tx, ty;
cin >> tx >> ty;
x[i] = tx, y[i] = ty;
G[ty].push_back(tx);
}
int k; cin >> k;
vector<int> path(k);
for(auto &x: path) cin >> x;
dijkstra(path[k-1]);
for(int i = 1; i <= n; ++i) G[i].clear();
for(int i = 0; i < m; ++i) G[x[i]].push_back(y[i]);
int ans1 = 0, ans2 = 0;
for(int i = 0; i < k-1; ++i) {
int flag = 0, cnt = 0;
for(auto v: G[path[i]]) {
if(dis[path[i]]-1 == dis[v]) {
if(v == path[i+1]) flag = 1;
cnt++;
}
}
if(!flag) ans1++, ans2++;
else if(cnt > 1) ans2++;
}
cout << ans1 << " " << ans2;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0);
cout.flags(ios::fixed);cout.precision(2);
//int t; cin >> t;
//while(t--)
run_case();
cout.flush();
return 0;
}