Language: C++

#include <iostream>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <vector>
#include <valarray>
#include <array>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <complex>
#include <random>

using namespace std;
using ll = long long;
using ull = unsigned long long;
using P = pair<int, int>;

/**
 * SCC, ??????????????£?????????????§£????????????????????????
 *
 * ?????¨??????????§???????
 *
 * template?????°???int V?????????????????§??°
 */
template<int V>
struct SCC {
    vector<int> g[V], rg[V];
    /// i-j?????????????????????
    void add(int i, int j) {
        g[i].push_back(j);
        rg[j].push_back(i);
    }

    vector<int> vs;
    bitset<V> used;
    void dfs(int v) {
        used[v] = true;
        for (int d: g[v]) {
            if (used[d]) continue;
            dfs(d);
        }
        vs.push_back(v);
    }
    int res[V]; /// res[i] = ??????i????±????????????£????????????ID
//    vector<int> scc[V]; /// scc[i] = i??????????????£?????????????±?????????????
    void rdfs(int v, int k) {
        used[v] = true;
        res[v] = k;
//        scc[k].push_back(v);
        for (int d: rg[v]) {
            if (used[d]) continue;
            rdfs(d, k);
        }
    }

    /**
     * ??????0..v-1????????????SCC?????????
     *
     * ???????????¨???????????£?????????????????°???????????????
     * ???????????????????????¨res[0..v-1], scc[0..v-1]????????±?????\???
     */
    int exec(int v) {
        vs.reserve(v+1);
//        fill_n(used, v, false);
        used.reset();
        for (int i = 0; i < v; i++) {
            if (used[i]) continue;
            dfs(i);
        }
//        fill_n(used, v, false);
        used.reset();
        int k = 0;
        for (int i = vs.size()-1; i >= 0; i--) {
            if (used[vs[i]]) continue;
            rdfs(vs[i], k);
            k++;
        }
        return k;
    }
};

const int MN = 1010;
const int MV = 1000010;
//const int SV = MV-3;
//const int TV = MV-1;
//const int TV2 = MV-2;
const int INF = 1<<28;

int SV, TV, TV2;
SCC<MV> scc;
//vector<int> sccg[MV];
//int dp[MV];

int solve() {
    scc.exec(TV+1);
    for (int i = 0; i < MV; i++) {
        scc.rg[i].clear();
    }
    for (int i = 0; i < MV; i++) {
        for (int j: scc.g[i]) {
            scc.rg[scc.res[i]].push_back(scc.res[j]);
        }
    }
    SV = scc.res[SV];
    TV = scc.res[TV];
    TV2 = scc.res[TV2];
    scc.res[TV] = -3;
    scc.res[TV2] = -2;
//    dp[scc.res[TV]] = -3;
//    dp[scc.res[TV2]] = -2;

    for (int i = MV-1; i >= 0; i--) {
        if (i == TV or i == TV2) continue;
        int ma = -INF;
        bool loop = false;
        for (int j: scc.rg[i]) {
            if (i == j) {
                loop = true;
                continue;
            }
            if (scc.res[j] == -INF) continue;
            ma = max(ma, scc.res[j]+2);
        }
        if (ma < -INF/2) ma = -INF;
        if (ma == -INF) {
            scc.res[i] = -INF;
            continue;
        }
        if (loop) ma = INF;
        scc.res[i] = ma;
    }
    if (scc.res[SV] > INF/2) return -1;
    return scc.res[SV];
}

int main() {
    static int sz[MN];
    static char ch[MN];
    static bool fi[MN] = {}, la[MN] = {};
    static vector<int> gs[MN], rgs[MN];
    fill_n(ch, MN, '$');

    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        sz[i] = (int)s.size();
        for (int j = 0; j < sz[i]; j++) {
            ch[i*10 + j] = s[j];
        }
        for (int j = 0; j < sz[i]-1; j++) {
            gs[i*10+j].push_back(i*10+j+1);
            rgs[i*10+j+1].push_back(i*10+j);
        }
        fi[i*10] = true;
        la[i*10 + sz[i] - 1] = true;
    }

    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y; x--; y--;
        gs[x*10+sz[x]-1].push_back(y*10);
        rgs[y*10].push_back(x*10+sz[x]-1);
    }

    n *= 10;
    SV = n*1000;
    TV2 = n*1000 + 1;
    TV = n*1000 + 2;
    fill_n(scc.res, MV, 0);
    for (int a = 0; a < n; a++) {
        for (int b = 0; b < n; b++) {
            int id1 = a*1000 + b;
            if (ch[a] == '$' or ch[b] == '$' or ch[a] != ch[b]) continue;
            if (fi[a] and la[b]) {
                scc.res[SV]++;
//                scc.add(SV, id1);
//                g[SV].push_back(id1);
            }
            if (a == b) {
                scc.res[id1]++;
//                scc.add(id1, TV);
//                g[id1].push_back(TV);
            }
            bool islast = false;
            for (int c: gs[a]) {
                if (c == b) {
                    islast = true;
                }
                for (int d: rgs[b]) {
                    int id2 = c*1000 + d;
                    if (ch[c] != ch[d]) continue;
                    scc.res[id1]++;
//                    scc.add(id1, id2);
//                    g[id1].push_back(id2);
                }
            }
            if (islast) {
                scc.res[id1]++;
//                scc.add(id1, TV2);
//                g[id1].push_back(TV2);
            }
        }
    }
    scc.res[SV]++;
    for (int i = 0; i < MV; i++) {
        scc.g[i].reserve(scc.res[i]);
    }
    fill_n(scc.res, MV, 0);
    for (int a = 0; a < n; a++) {
        for (int b = 0; b < n; b++) {
            int id1 = a*1000 + b;
            if (ch[a] == '$' or ch[b] == '$' or ch[a] != ch[b]) continue;
            if (fi[a] and la[b]) {
                scc.res[id1]++;
//                scc.add(SV, id1);
//                g[SV].push_back(id1);
            }
            if (a == b) {
                scc.res[TV]++;
//                scc.add(id1, TV);
//                g[id1].push_back(TV);
            }
            bool islast = false;
            for (int c: gs[a]) {
                if (c == b) {
                    islast = true;
                }
                for (int d: rgs[b]) {
                    int id2 = c*1000 + d;
                    if (ch[c] != ch[d]) continue;
                    scc.res[id2]++;
//                    scc.add(id1, id2);
//                    g[id1].push_back(id2);
                }
            }
            if (islast) {
                scc.res[TV2]++;
//                scc.add(id1, TV2);
//                g[id1].push_back(TV2);
            }
        }
    }
    scc.res[TV2]++;
    for (int i = 0; i < MV; i++) {
        scc.rg[i].reserve(scc.res[i]);
    }

    scc.add(SV, TV2);
    for (int a = 0; a < n; a++) {
        for (int b = 0; b < n; b++) {
            int id1 = a*1000 + b;
            if (ch[a] == '$' or ch[b] == '$' or ch[a] != ch[b]) continue;
            if (fi[a] and la[b]) {
                scc.add(SV, id1);
//                g[SV].push_back(id1);
            }
            if (a == b) {
                scc.add(id1, TV);
//                g[id1].push_back(TV);
            }
            bool islast = false;
            for (int c: gs[a]) {
                if (c == b) {
                    islast = true;
                }
                for (int d: rgs[b]) {
                    int id2 = c*1000 + d;
                    if (ch[c] != ch[d]) continue;
                    scc.add(id1, id2);
//                    g[id1].push_back(id2);
                }
            }
            if (islast) {
                scc.add(id1, TV2);
//                g[id1].push_back(TV2);
            }
        }
    }
//    g[SV].push_back(TV2);
    cout << solve() << endl;
    return 0;
}

Compiler output:
a.cc:40:5: error: 'bitset' does not name a type
   40 |     bitset<V> used;
      |     ^~~~~~
a.cc: In member function 'void SCC<V>::dfs(int)':
a.cc:42:9: error: 'used' was not declared in this scope
   42 |         used[v] = true;
      |         ^~~~
a.cc: In member function 'void SCC<V>::rdfs(int, int)':
a.cc:52:9: error: 'used' was not declared in this scope
   52 |         used[v] = true;
      |         ^~~~
a.cc: In member function 'int SCC<V>::exec(int)':
a.cc:70:9: error: 'used' was not declared in this scope
   70 |         used.reset();
      |         ^~~~