题目大意:有一个导航系统,会根据你当前的位置,规划到目的地的最短路线,给你一个有向图,和一条行驶路径,问你导航重新规划路径的最大次数和最小次数。
读题的时候题意特别不理解,何为最大次数,何为最小次数?
1 比如说当在一个点时,到终点的最短路线就那一个,也就说我只能走这一条,不用重新规划。
2 在一个点到终点的最短路径有多个,并且你下次要走的正好的其中的一个,这个时候,可以重新规划,也可以不重新规划。
3 在一个点到终点最短的路径中,你下次要走的点不是其中的一个,这个时候必须重新规划。
(有点绕,但是,,他就这么个意思)
思路:首先我们应该知道每个点到终点的最短距离,所以---反向图跑最短路
然后当在正向图中:
对路径中的某个点x,如果下次要走的点是与x相邻的点中最短的,并且唯一,那么不用重新规划。
如果不唯一:可以重新规划,也可以不重新规划,所以maxx++.
如果下次要走的点不是与x相邻的点中最短的 ,必须重新规划。maxx++,minn++;
#include<bits/stdc++.h> using namespace std; const int N=2E5+7; const int INF=1e9+7; int p[N]; int dis[N]; bool mark[N]; struct node{ int x,y; bool friend operator<(const node x1,const node y1){ return x1.y>y1.y; } }; vector<node>mp1[N],mp2[N]; void djstrea(int s){ memset(mark,0,sizeof(mark)); memset(dis,INF,sizeof(dis)); priority_queue<node>que; dis[s]=0; que.push({s,0}); while(que.size()){ node xx=que.top(); que.pop(); if(mark[xx.x]==1) continue ; mark[xx.x]=1; for(int i=0;i<mp1[xx.x].size();i++){ int dx=mp1[xx.x][i].x; int dy=mp1[xx.x][i].y; if(mark[dx]==0&&dis[dx]>dis[xx.x]+dy){ dis[dx]=dis[xx.x]+dy; que.push({dx,dis[dx]}); } } } } int main(){ int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; mp1[y].push_back({x,1}); mp2[x].push_back({y,1}); } int k; cin>>k; for(int i=1;i<=k;i++) cin>>p[i]; for(int i=1;i<=n;i++) dis[i]=INF; djstrea(p[k]); int minn=0,maxx=0; for(int i=1;i<k;i++){ int c=dis[p[i+1]]; int cnt1=0,cnt2=0; int x1=p[i]; for(int j=0;j<mp2[x1].size();j++){ if(dis[mp2[x1][j].x]==c) cnt1++; if(dis[mp2[x1][j].x]<c) cnt2++; } if(cnt2!=0){ minn++; maxx++; } else if (cnt1>1) maxx++; } cout<<minn<<" "<<maxx<<endl; return 0; }