"Cattle off NOIP sprint simulation game" cave

Topic Summary

Given a \ (n-\) points, \ (m \) have edges directed graph, given \ (Q \) group query, each query given \ (S, T, L \) , asks is there one from \ (S \) to \ (T \) path just after \ (L \) sides, goes a path may be repeated.
\ (n \ le 100, m \ le 10000, Q \ le 1000, l \ le 10 ^ 9 \)

Problem-solving ideas

Consider a pre-array \ (F [X] [I] [J] \) : indicates whether the \ (I \) come \ (J \) after \ (2 ^ k \) edges.
This can be run directly multiply Floyd, then we can consider doubling from \ (s \) the beginning of each bfs have extended some nodes, as long as the judge \ (t \) belongs to the last set of nodes.

Details Notes

  • Some other methods may often require card, such as a fairy \ (O (\ frac {n ^ 3} {64} Q \ log_ {256} l) \)

Reference Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <vector>
#include <cmath>
#include <ctime>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < typename T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while (!isdigit(c)) f |= c == '-', c = getchar();
    while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
    s = f ? -s : s;
}

const int _ = 102;

int n, m, f[31][_][_], vis[_];
vector < int > vec;

inline void expand(int x) {
    memset(vis, 0, sizeof (int) * (n + 1));
    for (rg int i = 1; i <= n; ++i)
        for (rg int j = 0; j < vec.size(); ++j)
            if (f[x][vec[j]][i]) { vis[i] = 1; break; }
    vec.clear();
    for (rg int i = 1; i <= n; ++i) if (vis[i]) vec.push_back(i);
}

inline void solve() {
    int l, x, y; read(l), read(x), read(y);
    vec.clear(); vec.push_back(x);
    for (rg int i = 30; ~i; --i)
        if (l >> i & 1) expand(i);
    for (rg int i = 0; i < vec.size(); ++i)
        if (vec[i] == y) { puts("YES"); return; }
    puts("NO");
}

int main() {
//  file("cave");
    read(n), read(m);
    for (rg int u, v, i = 1; i <= m; ++i)
        read(u), read(v), f[0][u][v] = 1;
    for (rg int x = 1; x <= 30; ++x)
        for (rg int k = 1; k <= n; ++k)
            for (rg int i = 1; i <= n; ++i)
                for (rg int j = 1; j <= n; ++j)
                    f[x][i][j] |= f[x - 1][i][k] & f[x - 1][k][j];
    int T; read(T);
    while (T--) solve();
    return 0;
}

End Sahua \ (qwq \)

Guess you like

Origin www.cnblogs.com/zsbzsb/p/11759797.html