:heavy_check_mark: test/Math/difference_constraints_solver/aoj-0304.cpp

Depends on

Code

// competitive-verifier: PROBLEM https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0304

#include "Math/difference_constraints_solver.hpp"
#include <bits/stdc++.h>

using namespace std;

int main()
{
    int N, C;
    cin >> N >> C;

    auto parse = [](string S) -> tuple<int, string, int, char, int>
    {
        int a = -1, b = -1, d = -1;
        string o;
        char s;

        int pre = 0;
        for (int i = 0; i < ssize(S); i++)
        {
            if (isdigit(S[i]))
            {
                continue;
            }

            if (a == -1)
            {
                a = stoi(string(S.begin() + pre, S.begin() + i));
                if (S[i] == '*')
                {
                    o = "*";
                    pre = i + 1;
                }
                else
                {
                    o = string(1, S[i]) + string(1, S[i + 1]);
                    i++;
                    pre = i + 1;
                }
            }
            else if (b == -1)
            {
                b = stoi(string(S.begin() + pre, S.begin() + i));
                s = S[i];
                pre = i + 1;
            }
        }
        d = stoi(string(S.begin() + pre, S.end()));

        return {a, o, b, s, d};
    };

    vector<array<int, 3>> abd;
    DifferenceConstraintsSolver<long long> solver(N);

    for (int i = 0; i < C; i++)
    {
        string S;
        cin >> S;
        auto [a, o, b, s, d] = parse(S);
        a--, b--;

        if (o == "<=")
        {
            swap(a, b);
        }

        if (o == "*")
        {
            if (s == '-')
            {
                solver.add_leq_constraint(a, b, d);
                solver.add_leq_constraint(b, a, d);
            }
            if (s == '+')
            {
                abd.push_back({a, b, d});
            }
        }
        else
        {
            // 0 <= a - b <= d
            if (s == '-')
            {
                solver.add_geq_constraint(a, b, 0);
                solver.add_leq_constraint(a, b, d);
            }

            // d <= a - b
            if (s == '+')
            {
                solver.add_geq_constraint(a, b, d);
            }
        }
    }

    long long ans = -1;
    // abd の制約については全通り確かめる。
    for (int bit = 0; bit < (1 << ssize(abd)); bit++)
    {
        DifferenceConstraintsSolver<long long> temp = solver;
        for (int i = 0; i < ssize(abd); i++)
        {
            auto [a, b, d] = abd[i];
            if ((bit >> i) & 1)
            {
                temp.add_geq_constraint(a, b, d);
            }
            else
            {
                temp.add_geq_constraint(b, a, d);
            }
        }

        auto result = temp.solve(0);
        if (!result.first)
        {
            continue;
        }

        if (*min_element(result.second.begin(), result.second.end()) < 0)
        {
            continue;
        }

        long long sub_ans = *max_element(result.second.begin(), result.second.end());
        ans = max(ans, sub_ans);
    }

    if (ans == solver.INF)
    {
        cout << "inf" << endl;
    }
    else
    {
        cout << ans << endl;
    }

    return 0;
}
#line 1 "test/Math/difference_constraints_solver/aoj-0304.cpp"
// competitive-verifier: PROBLEM https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0304

#line 1 "Math/difference_constraints_solver.hpp"
#include <bits/stdc++.h>
using namespace std;

template <typename T>
struct DifferenceConstraintsSolver
{
    struct Edge
    {
        int from, to;
        T cost;
        Edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    };

    const T INF = numeric_limits<T>::max() / 2;
    int N;
    vector<Edge> edges;

    DifferenceConstraintsSolver(int n) : N(n) {}

    // 制約: x_i - x_j <= c を追加します。
    void add_leq_constraint(int i, int j, T c)
    {
        assert(0 <= i && i < N);
        assert(0 <= j && j < N);

        edges.emplace_back(j, i, c);
    }

    // 制約: x_i - x_j >= c を追加します。
    void add_geq_constraint(int i, int j, T c)
    {
        assert(0 <= i && i < N);
        assert(0 <= j && j < N);

        edges.emplace_back(i, j, -c);
    }

    // 制約: x_i - x_j == c を追加します。
    void add_eq_constraint(int i, int j, T c)
    {
        assert(0 <= i && i < N);
        assert(0 <= j && j < N);

        add_leq_constraint(i, j, c);
        add_geq_constraint(i, j, c);
    }

    pair<bool, vector<T>> solve(int S = 0)
    {
        assert(0 <= S && S < N);

        vector<T> result(N, INF);
        result[S] = 0;

        for (int iter = 0; iter < N - 1; ++iter)
        {
            for (const auto &e : edges)
            {
                if (result[e.from] != INF)
                {
                    result[e.to] = min(result[e.to], result[e.from] + e.cost);
                }
            }
        }

        for (const auto &e : edges)
        {
            if (result[e.from] != INF && result[e.to] > result[e.from] + e.cost)
            {
                return {false, {}};
            }
        }

        return {true, result};
    }
};
#line 5 "test/Math/difference_constraints_solver/aoj-0304.cpp"

using namespace std;

int main()
{
    int N, C;
    cin >> N >> C;

    auto parse = [](string S) -> tuple<int, string, int, char, int>
    {
        int a = -1, b = -1, d = -1;
        string o;
        char s;

        int pre = 0;
        for (int i = 0; i < ssize(S); i++)
        {
            if (isdigit(S[i]))
            {
                continue;
            }

            if (a == -1)
            {
                a = stoi(string(S.begin() + pre, S.begin() + i));
                if (S[i] == '*')
                {
                    o = "*";
                    pre = i + 1;
                }
                else
                {
                    o = string(1, S[i]) + string(1, S[i + 1]);
                    i++;
                    pre = i + 1;
                }
            }
            else if (b == -1)
            {
                b = stoi(string(S.begin() + pre, S.begin() + i));
                s = S[i];
                pre = i + 1;
            }
        }
        d = stoi(string(S.begin() + pre, S.end()));

        return {a, o, b, s, d};
    };

    vector<array<int, 3>> abd;
    DifferenceConstraintsSolver<long long> solver(N);

    for (int i = 0; i < C; i++)
    {
        string S;
        cin >> S;
        auto [a, o, b, s, d] = parse(S);
        a--, b--;

        if (o == "<=")
        {
            swap(a, b);
        }

        if (o == "*")
        {
            if (s == '-')
            {
                solver.add_leq_constraint(a, b, d);
                solver.add_leq_constraint(b, a, d);
            }
            if (s == '+')
            {
                abd.push_back({a, b, d});
            }
        }
        else
        {
            // 0 <= a - b <= d
            if (s == '-')
            {
                solver.add_geq_constraint(a, b, 0);
                solver.add_leq_constraint(a, b, d);
            }

            // d <= a - b
            if (s == '+')
            {
                solver.add_geq_constraint(a, b, d);
            }
        }
    }

    long long ans = -1;
    // abd の制約については全通り確かめる。
    for (int bit = 0; bit < (1 << ssize(abd)); bit++)
    {
        DifferenceConstraintsSolver<long long> temp = solver;
        for (int i = 0; i < ssize(abd); i++)
        {
            auto [a, b, d] = abd[i];
            if ((bit >> i) & 1)
            {
                temp.add_geq_constraint(a, b, d);
            }
            else
            {
                temp.add_geq_constraint(b, a, d);
            }
        }

        auto result = temp.solve(0);
        if (!result.first)
        {
            continue;
        }

        if (*min_element(result.second.begin(), result.second.end()) < 0)
        {
            continue;
        }

        long long sub_ans = *max_element(result.second.begin(), result.second.end());
        ans = max(ans, sub_ans);
    }

    if (ans == solver.INF)
    {
        cout << "inf" << endl;
    }
    else
    {
        cout << ans << endl;
    }

    return 0;
}

Test cases

Env Name Status Elapsed Memory
g++ 00_sample_00.in :heavy_check_mark: AC 5 ms 3 MB
g++ 00_sample_01.in :heavy_check_mark: AC 4 ms 3 MB
g++ 00_sample_02.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_00.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_01.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_02.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_03.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_04.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_05.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_06.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_07.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_08.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_09.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_10.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_11.in :heavy_check_mark: AC 4 ms 3 MB
g++ 02_case_12.in :heavy_check_mark: AC 4 ms 3 MB
g++ 03_critical_00.in :heavy_check_mark: AC 4 ms 3 MB
g++ 03_critical_01.in :heavy_check_mark: AC 4 ms 3 MB
g++ 04_large_00.in :heavy_check_mark: AC 4 ms 3 MB
g++ 04_large_01.in :heavy_check_mark: AC 4 ms 3 MB
g++ 04_large_02.in :heavy_check_mark: AC 5 ms 3 MB
g++ 04_large_03.in :heavy_check_mark: AC 6 ms 3 MB
Back to top page