algo — C++23 日本語リファレンス GitHub

test/aoj/challenge/2704.test.cpp

AC · 最終更新 2026-09-06 · GitHub

問題: https://onlinejudge.u-aizu.ac.jp/problems/2704

依存するヘッダ(1)
実装
// competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/2704
#include <iostream>
#include "parser/cfg_graph.hpp"

// Stamp Rally: 辺ラベルの列が正しい数式 (下の CNF 文法) になる s->t の歩道が
// 存在するか。文法をグラフに適用する文脈自由到達可能性 (CYK のグラフ版) で解く。
//   E -> E PT | T SF | a | LP ER | LB EB
//   T -> T SF | a | LP ER | LB EB
//   F -> a | LP ER | LB EB
//   PT -> PLUS T,  SF -> STAR F,  ER -> E RP,  EB -> E RB
//   PLUS='+', STAR='*', LP='(', RP=')', LB='[', RB=']'
// (元の文法 E->T|E+T, T->F|T*F, F->a|(E)|[E] を単位規則除去して CNF 化)
enum { E, T, F, PT, SF, ER, EB, PLUS, STAR, LP, RP, LB, RB, NUM_SYM };

int main() {
    int n, m, s, t;
    while (std::cin >> n >> m >> s >> t && (n || m || s || t)) {
        CykGraph g(n, NUM_SYM);
        for (int i = 0; i < m; ++i) {
            int a, b;
            char c;
            std::cin >> a >> b >> c;
            --a, --b;
            switch (c) {
                case 'a': g.add(E, a, b), g.add(T, a, b), g.add(F, a, b); break;
                case '+': g.add(PLUS, a, b); break;
                case '*': g.add(STAR, a, b); break;
                case '(': g.add(LP, a, b); break;
                case ')': g.add(RP, a, b); break;
                case '[': g.add(LB, a, b); break;
                case ']': g.add(RB, a, b); break;
            }
        }
        g.add_rule(E, E, PT), g.add_rule(E, T, SF), g.add_rule(E, LP, ER), g.add_rule(E, LB, EB);
        g.add_rule(T, T, SF), g.add_rule(T, LP, ER), g.add_rule(T, LB, EB);
        g.add_rule(F, LP, ER), g.add_rule(F, LB, EB);
        g.add_rule(PT, PLUS, T), g.add_rule(SF, STAR, F);
        g.add_rule(ER, E, RP), g.add_rule(EB, E, RB);
        g.solve();
        std::cout << (g.get(E, s - 1, t - 1) ? "Yes" : "No") << '\n';
    }
    return 0;
}