Y
K
N
U
F

题解:luoguP12414 「YLLOI-R1-T3」一路向北

大家好,我数学不好,所以我用 dfs 通过了这道题。

观察题目,很容易发现其实就是给出了 \(n\) 个双端队列,用一个 \(0\) 作为“外来元素”进行题目所说的操作。所谓操作也就是将手中的现有元素 \(has\) 加入到第 \(has\) 个队列队尾并将队头元素弹出作为新的 \(has\)。如果 \(0\) 在操作中永远不会出现就输出 Yes,否则输出 No。

那这不就是 dfs 么。

考虑直接用 \(n\) 个双端队列模拟,每一个队列作为一个可能的起点,对于每一个情况进行搜索,定义一个 \(inf\) 作为 \(0\) 永不出现的临界值,一旦搜索数超过了 \(inf\) 就直接输出 Yes,反之若每一个情况都遍历过也没能输出 Yes 则输出 No。


一些细节:

显然不可以用暴力赋值来开启每一次的搜索(像这样):

for(int i=1;i<=n;i++){
    not0=0;
    for(int i=1;i<=n;i++)//这个循环是罪魁祸首,n^2的赋值比代码主体都慢。
        a[i]=b[i];
    a[i].push_back(0);
    int aaa = a[i].front();
    a[i].pop_front();
    if(dfs(aaa)){
        ender=1;
        cout<<"Yes"<<'\n';
        break;
    }
}

会 TLE。

可以直接将双端队列作为参数传入函数,省去大量的赋值,可以 AC。


完整代码:

// code by 樓影沫瞬_Hz17
#include <bits/stdc++.h>
using namespace std;
int in();
typedef deque<int> deq;
int n, m, not0;
deq b[100100];

bool dfs(int has, deq a[]) {// 搜索的主体
    not0++;
    if (has == 0)// 0回到了手里
        return 0;
    if (not0 > 100000)// 100000也就是上文说的 inf (已经最优,少 1 都不行,同一个机房的dalao有证明出来为什么是 100000 的,但我不会)。
        return 1;
    a[has].push_back(has);
    int tem = a[has].front();
    a[has].pop_front();
    return dfs(tem, a);
}

bool work(int i, deq a[]) {// 每次搜索的起点
    not0 = 0;
    a[i].push_back(0);
    int tem = a[i].front();
    a[i].pop_front();
    return dfs(tem, a);
}

int main() {
    int T;
    T = in();
    while (T--) {
        n = in(), m = in();
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                b[i].push_back(in());
        bool ender = 0;
        for (int i = 1; i <= n; i++)
            if (work(i, b)) {// 直接传参,不然会 TLE
                ender = 1;
                cout << "Yes\n";
                break;
            }
        if (!ender)// 没有输出过 Yes
            cout << "No\n";
        for (int i = 1; i <= n; i++)
            b[i].clear();// 多测不清空,__________。
    }
    return 0;
}
int in() {// 快读
    int n = 0, f = 0, c = getchar_unlocked();
    while (c <= '-')
        f = f ? 1 : c == '-', c = getchar_unlocked();
    while (!(c < '0' || c > '9'))
        n = (n << 1) + (n << 3) + (c ^ 48), c = getchar_unlocked();
    return f ? -n : n;
}
posted @ 2025-07-07 21:47  樓影沫瞬_Hz17  阅读(11)  评论(0)    收藏  举报