Submission #1183749

#TimeUsernameProblemLanguageResultExecution timeMemory
1183749vux2codeSailing Race (CEOI12_race)C++20
0 / 100
283 ms8952 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll maxN = 500 + 5;
const ll inf64 = (ll)1e18;

ll n, k;
ll f1[maxN][maxN][2]; // for two‐segment DP (one crossing)
ll f2[maxN][maxN][2]; // for simple path DP (no crossing)
vector<ll> adj[maxN];

// Next harbor in circular order
ll nx(ll x) {
    x++;
    if (x > n) x -= n;
    return x;
}

// is x strictly between st and en along the circle (counterclockwise)?
bool irg(ll st, ll en, ll x) {
    if (st == en || en == nx(st)) return false;
    if (st > en) return (x > st || x < en);
    return (st < x && x < en);
}

// inrange depending on direction flag
bool inrange(ll st, ll en, bool dir, ll x) {
    return dir ? irg(st, en, x) : irg(en, st, x);
}

// DP for one‐crossing case: you can switch to the other arc once
ll fin2d(ll st, ll en, bool dir) {
    ll &res = f1[st][en][dir];
    if (res != -1) return res;
    res = 0;
    for (ll i : adj[st]) {
        if (!inrange(st, en, dir, i)) continue;
        // either stay on this arc or switch arcs at i
        res = max(res,
                  1 + max(
                      fin2d(i, en, dir),
                      fin2d(i, st, !dir)
                  )
        );
    }
    return res;
}

// DP for classical no‐crossing: longest simple path from st to en along one arc
ll finz(ll st, ll en, bool dir) {
    ll &res = f2[st][en][dir];
    if (res != -1) return res;
    if (st == en) return res = 1;
    res = -inf64;
    for (ll i : adj[st]) {
        if (!inrange(st, en, dir, i)) continue;
        ll tmp = finz(i, en, dir);
        if (tmp > 0) res = max(res, tmp + 1);
    }
    return res;
}

// DP wrapper for one‐crossing: try a single cross after the first segment
ll fin1d(ll st, ll en, bool dir) {
    ll ans = 0;
    for (int mid = 1; mid <= n; mid++) {
        if (!inrange(st, en, dir, mid)) continue;
        ll prefix = finz(st, mid, dir);
        if (prefix <= 0) continue;
        for (ll nxt : adj[mid]) {
            if (inrange(st, en, dir, nxt)) continue;
            // cross at (mid -> nxt)
            ans = max(ans, prefix + fin2d(nxt, st, dir));
            ans = max(ans, prefix + fin2d(nxt, en, !dir));
        }
    }
    return ans;
}

void solve() {
    cin >> n >> k;
    // read graph
    for (int i = 1; i <= n; i++) {
        adj[i].clear();
        ll x;
        while (cin >> x && x > 0) {
            adj[i].push_back(x);
        }
    }
    // init DP tables
    memset(f1, -1, sizeof f1);
    memset(f2, -1, sizeof f2);

    ll bestLen = 0, bestStart = 1;
    // try every possible first stage s->t
    for (int s = 1; s <= n; s++) {
        for (ll t : adj[s]) {
            if (k == 0) {
                // classical: one segment s->t + simple path back
                for (int dir = 0; dir < 2; dir++) {
                    ll verts = finz(t, s, dir);
                    if (verts > 0) {
                        ll edges = 1 + (verts - 1);
                        if (edges > bestLen) {
                            bestLen = edges;
                            bestStart = s;
                        }
                    }
                }
            } else {
                // one crossing allowed
                for (int dir = 0; dir < 2; dir++) {
                    ll extra = fin1d(t, s, dir);
                    ll edges = 1 + extra;
                    if (edges > bestLen) {
                        bestLen = edges;
                        bestStart = s;
                    }
                }
            }
        }
    }

    cout << bestLen << " " << bestStart << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    solve();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...