ABC 132 | E - Hopscotch Addict
题目描述
给定一个无权有向图\(G\)(\(N\)个点,\(M\)条边),给定起点\(S\)和终点\(T\),问是否可以从\(S\)走到\(T\)。如果可以到达,输出最少步数;如果不能到达,输出-1。
规定一步如下:沿\(G\)中边的指向走\(3\)条边记作一步
数据范围
- \(2 \le N \le 10^5\)
- \(0 \le M \le \min(10^5,N(N−1))\)
题解
- 该题是一个分层图的典型问题,对于分层图问题,整体看上去是个
bfs,之所以要分层,主要是考虑到状态表示和状态转移。 - 比如该题要求的答案不是简单的\(dist[T]\),而是\(dist[T][0]\),不是从\(S\)到\(T\)的最短路径的长度,而是从\(S\)到\(T\)且长度\(\mod 3 = 0\)的最短路径的长度,输出的结果是\(dist[T][0] / 3\)。
- 即该题可以通过思考答案的表示上入手,而长度的记录本质上是个递推,类似于\(dp\)中的状态转移。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> pii;
const int N = 1e5 + 10;
int h[N], e[N], ne[N], idx;
int n, m;
int st, ed;
int dist[N][10];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void bfs(){
memset(dist, 0x3f, sizeof dist);
queue<pii> q;
q.push({st, 0});
dist[st][0] = 0;
while(q.size()){
auto t = q.front();
q.pop();
int ver = t.first, distance = t.second;
for(int i = h[ver]; i != -1; i = ne[i]){
int j = e[i];
int k = (distance + 1) % 3;
if(dist[j][k] > dist[ver][distance] + 1){
dist[j][k] = dist[ver][distance] + 1;
q.push({j, k});
}
}
}
return;
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
for(int i = 1; i <= m; i ++){
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
}
scanf("%d%d", &st, &ed);
bfs();
if(dist[ed][0] == 0x3f3f3f3f) puts("-1");
else printf("%d\n", dist[ed][0] / 3);
return 0;
}

浙公网安备 33010602011771号