http://codeforces.com/contest/1320/problem/B题目链接
题目给你一个有向图,然后再给你一条路径<u,v>,每次最短路的路径变化的话会重新导航,让你求出在<u,v>这条路径上重新导航次数的最小值和最大值。
题意很明了,可先用dij求出终点到所有点的最短路;
然后对司机将要走的路线逐点进行判断;每到一个点分两种情况
1:如果终点到该点的距离与终点到该点之后将要走的点的距离之差不为1,说明司机一定没有按照导航给出的路线走 此时最大最小值都要加1;
2:如果终点到该点的距离与终点到该点之后将要走的点的距离之差为1,分两种情况
1.如果有多个当前点的子点满足 子点到终点的距离+1=当前点 ;则有可能司机走了导航给的路线,也可能没走,那么调整次数最大值+1;
2.如果只有一个当前点的子点满足 子点到终点的距离+1=当前点 ;则司机一定走了导航给的路线,不做变化。
由此,最后便得到了调整次数的最大值和最小值输出即可
#include<bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define si size() const int maxn=2e5+5; vector<long long>g[maxn],G[maxn]; long long a[maxn],d[maxn],vis[maxn]; long long n,m,p; void dij(){ for(int i=1;i<=n;i++) vis[i]=0,d[i]=1e9; priority_queue<pair<long long ,long long>>q; q.push(mp(0,a[p])); d[a[p]]=0; while(q.size()) { long long u=q.top().second; q.pop(); if(vis[u]) continue; vis[u]=1; for(int i=0;i<G[u].size();i++) { long long v=G[u][i]; if(d[v]>d[u]+1){ d[v]=d[u]+1; q.push(mp(-d[v],v)); } } } } int main() { cin>>n,cin>>m; for(int i=1;i<=m;i++) { long long u,v; cin>>u>>v; g[u].pb(v); G[v].pb(u); } cin>>p; for(int i=1;i<=p;i++) cin>>a[i]; dij(); long long ans1=0,ans2=0; for(int i=1;i<p;i++) { long long u=a[i],v=a[i+1]; if(d[u]!=d[v]+1)ans1++,ans2++; else { for(int j=0;j<g[u].size();j++){ long long x=g[u][j]; if(d[x]==d[u]-1&&x!=v){ ans2++;break; } } } } cout<<ans1<<" "<<ans2; }