Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round) 比赛人数5638
[codeforces 1321D] Navigation System 逆向最短路+题意解读
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.ml/contest/1321/problem/D
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
D - Navigation System | GNU C++11 | Accepted | 93 ms | 13100 KB |
不管中途如何变化,最终都要到达指定的终点,故从终点出发,建立逆向的最短路,这点是容易想到的。
题意解读:
1.图是有向图
证据1,题中给的图形
证据2,文字说明
which means that each ordered pair (u,v) appears at most once
ordered pair有序对
2.p1, p2, ..., pk, where p1=s, pk=t构成的新路径中,相邻两点,间距是1.
证据如下
Today he has chosen the following path to his workplace: p1, p2, ..., pk, where p1=s, pk=t, and all other elements of this sequence are the intermediate intersections, listed in the order Polycarp arrived at them.
listed in the order Polycarp arrived at them.按Polycarp到达的顺序排列。故没有到达的交叉口是不会出现的,有到达的一定会出现。
3.当前点之后,可能的路径有多种(不止一种),无论有多少种,那么就叫rebuilds一次
证据,详细看题中rebuilds的字体加粗位置的语句。
#include <stdio.h>
#define maxn 200010
#define INF 200010
int head[maxn],cnt,n,m,d[maxn],q[maxn*10],vis[maxn],k,p[maxn],least,more,used[maxn];
struct node{
int to,next;
}e[maxn];
void add_edge(int u,int v){//邻接表
cnt++,e[cnt].to=v,e[cnt].next=head[u],head[u]=cnt;
}
void init(){
int i,u,v;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d",&u,&v);
add_edge(v,u);//反向存储,要研究t->s的路径
}
scanf("%d",&k);
for(i=1;i<=k;i++)scanf("%d",&p[i]);
}
void spfa(int x){//spfa算法
int u,v,b,i,h,t;
for(i=1;i<=n;i++)d[i]=INF;
d[x]=0,h=t=1,q[t]=x,t++,vis[x]=1;
while(h<t){
u=q[h];
for(b=head[u];b;b=e[b].next){
v=e[b].to;
if(d[v]>d[u]+1){
used[v]=1,d[v]=d[u]+1;
if(!vis[v])vis[v]=1,q[t]=v,t++;
}else if(d[v]==d[u]+1)used[v]++;
}
vis[u]=0,h++;
}
}
void solve(){
int i;
for(i=2;i<=k;i++)
if(d[p[i-1]]!=d[p[i]]+1)least++;//相邻两个点不可达
else if(used[p[i-1]]>1)more++;//相邻两个点可达,但有多种走法
printf("%d %d\n",least,least+more);
}
int main(){
init();
spfa(p[k]);
solve();
return 0;
}