AT4733 [ABC132E] Hopscotch Addict 题解

题目传送门


思路

分层图跑最短路。


\(∵\) 题目中说每次只能走 \(3\) 步, \(∴\) 我们可以把一条边拆成三条边,
拆成 \(1\)\(2\)\(2\)\(3\)\(3\)\(2\) 的三条边权为 \(1\) 的边。

连边时,可以把边建在所有边的后面:

add (x, y + n) ;
add (x + n, y + n * 2) ;
add (x + n * 2, y) ;

然后跑一遍从 \(S\) 开始的最短路。

\(∵\) 因为每个点都跑了三遍,\(∴\) 最终答案 \(val_t \div 3\)

其他题解跑最短路大多数用的是 Dijkstra ,我就用 SPFA 写吧。

代码如下:

#include <stdio.h>
#include <cstring>
#include <queue>

using namespace std;

const int N = 3e5 + 10; // 这里数组要开三倍,因为要连三条边。
const int INF = 0x3f3f3f3f;

void add (int, int) ;
void SPFA (int) ;

bool f[N];

int n, m;
int s, t;
int tot;
int val[N];
int now[N], pre[N], son[N];

queue <int> q;

main () {
    scanf ("%d %d", &n, &m) ;
    
    for (int x, y; m; -- m) {
        scanf ("%d %d", &x, &y) ;
        
        // 连三条边。
        add (x, y + n) ;
        add (x + n, y + n * 2) ;
        add (x + n * 2, y) ;
    }
        
    scanf ("%d %d", &s, &t) ;
    
    SPFA (s) ;
    
    if (val[t] == INF)
        puts ("-1") ;
    else
        printf ("%d", val[t] / 3) ; // 最终答案除以三。
}

void add (int x, int y) { // 建图。
    pre[++ tot] = now[x];
    son[tot] = y;
    now[x] = tot;
}

void SPFA (int s) { // SPFA 求最短路。
    memset (val, 0x3f, sizeof val) ;
    val[s] = 0;
    q.push (s) ;
    
    for (; !q.empty () ;) {
        int x = q.front () ;
        q.pop () ;
        f[x] = 1;
        
        for (int i = now[x]; i; i = pre[i]) {
            int y = son[i];
            
            if (val[y] > val[x] + 1) {
                val[y] = val[x] + 1;
                   
                if (!f[y]) {
                    f[y] = 1;
                    q.push (y) ;
                }
            }
        }
    }
}

完结撒花 \(\sim\sim\sim\)

posted @ 2023-07-01 11:20  liukejie  阅读(13)  评论(0编辑  收藏  举报