Submission #1044238

# Submission time Handle Problem Language Result Execution time Memory
1044238 2024-08-05T08:14:08 Z 우민규(#11006) Parking (CEOI22_parking) C++17
50 / 100
151 ms 29996 KB
#include <bits/stdc++.h>
using namespace std;

int n, m;
vector<int> fst, snd;
// bottom -> up then true, up -> bottom then false
vector<vector<int>> adj;
vector<int> type;
// determine type

vector<bool> visited, is_selfloop;
vector<vector<int>> locs;

enum Component {
    TrivialPath,
    SplitPath,
    PerfectCycle,
    SplitCycle,
    ComplexCycle,
    SelfLoop,
    EmptySelfLoop,
};

// {amt of top, saw path}
pair<int, bool> dfs(int node) {
    visited[node] = true;
    int top_amt = type[node] == 3;
    bool is_path = false;
    for (auto v : adj[node]) {
        if (visited[v]) continue;
        if (v == 0) {
            is_path = true;
        } else {
            auto [tt, ip] = dfs(v);
            top_amt += tt;
            is_path |= ip;
        }
    }
    return {top_amt, is_path};
}

Component component_type(int node) {
    if (is_selfloop[node]) return SelfLoop;

    auto [top_amt, is_path] = dfs(node);
    if (is_path) {
        if (top_amt) return SplitPath;
        return TrivialPath;
    }
    if (top_amt > 1) return ComplexCycle;
    if (top_amt) return SplitCycle;
    return PerfectCycle;
}

vector<pair<int, int>> drives;

vector<int> auxs;

void trivial_contraction(int node) {
    if (node == 0 || type[node] == 3) return;
    int a = locs[node][0];
    int b = locs[node][1];
    if (a == b) return;
    bool can_a_pop = snd[a] == 0 || snd[a] == node;
    bool can_b_pop = snd[b] == 0 || snd[b] == node;
    bool can_a_recv = fst[a] == node && snd[a] == 0;
    bool can_b_recv = fst[b] == node && snd[b] == 0;
    if (can_b_pop && can_a_recv) {
        drives.push_back({b, a});
        fst[a] = snd[a] = node;
        locs[node] = {a, a};
        if (snd[b] == node) {
            snd[b] = 0;
            trivial_contraction(fst[b]);
        } else {
            assert(fst[b] == node);
            fst[b] = 0;
            auxs.push_back(b);
        }
    } else if (can_a_pop && can_b_recv) {
        drives.push_back({a, b});
        fst[b] = snd[b] = node;
        locs[node] = {b, b};
        if (snd[a] == node) {
            snd[a] = 0;
            trivial_contraction(fst[a]);
        } else {
            assert(fst[a] == node);
            fst[a] = 0;
            auxs.push_back(a);
        }
    }
}

void trivial_component_contraction(int node) {
    visited[node] = true;
    trivial_contraction(node);
    for (auto v : adj[node]) {
        if (visited[v]) continue;
        trivial_component_contraction(v);
    }
}

void perfect_cycle_contraction(int node) {
    assert(!auxs.empty());
    int aux = auxs.back();
    auxs.pop_back();
    
    int a = locs[node][0], b = locs[node][1];
    if (snd[a] == node) {
        drives.push_back({a, aux});
        snd[a] = 0;
        fst[aux] = node;
        locs[node][0] = aux;
        trivial_contraction(fst[a]);
    }
    if (snd[b] == node) {
        drives.push_back({b, aux});
        snd[b] = 0;
        fst[aux] = node;
        locs[node][1] = aux;
        trivial_contraction(fst[b]);
    }
}

vector<int> component_top_nodes;
void find_top_node_and_contract_ends(int node) {
    visited[node] = true;
    if (type[node] == 3) component_top_nodes.push_back(node);
    trivial_contraction(node);
    for (auto v : adj[node]) if (v != 0 && !visited[v]) find_top_node_and_contract_ends(v);
}

void with_top_contraction(int node) {
    component_top_nodes.clear();
    find_top_node_and_contract_ends(node);
    for (auto v : component_top_nodes) {
        assert(!auxs.empty());
        int aux = auxs.back();
        auxs.pop_back();

        int a = locs[v][0];
        int b = locs[v][1];
        locs[v][0] = locs[v][1] = aux;

        drives.push_back({a, aux});
        drives.push_back({b, aux});
        snd[a] = 0, snd[b] = 0;
        fst[aux] = snd[aux] = v;
        
        trivial_contraction(fst[a]);
        trivial_contraction(fst[b]);
    }
}


void solve() {
    cin >> n >> m;
    adj.assign(n + 1, {}), type.assign(n + 1, 0), visited.assign(n + 1, false), is_selfloop.assign(n + 1, false);
    locs.assign(n + 1, {});
    int num_type[7]{};
    for (int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        if (a) type[a] = 2 * type[a];
        if (b) type[b] = 2 * type[b] + 1;
        fst.push_back(a), snd.push_back(b);
        adj[a].push_back(b), adj[b].push_back(a);
        locs[a].push_back(i), locs[b].push_back(i);
        if (a == 0 && b == 0) {
            num_type[EmptySelfLoop] += 1;
            auxs.push_back(i);
        }
        if (a == b) {
            is_selfloop[a] = true;
        }
    }
    // determine all endpoints
    vector<pair<Component, int>> sources;
    for (int i = 1; i <= n; ++i) {
        if (!visited[i]) {
            Component cur = component_type(i);
            num_type[cur] += 1;
            sources.push_back({cur, i});
        }
    }

    int req_moves = num_type[PerfectCycle];
    for (int i = 1; i <= n; ++i) {
        if (is_selfloop[i]) continue;
        req_moves += 1;
        if (type[i] == 3) req_moves += 1;
    }

    // Check if it's possible
    num_type[EmptySelfLoop] += num_type[TrivialPath];
    num_type[TrivialPath] = 0;
    if (num_type[EmptySelfLoop] == 0 &&
        (num_type[SplitPath] > 0 || num_type[PerfectCycle] > 0 ||
         num_type[SplitCycle] > 0 || num_type[ComplexCycle] > 0)) {
        cout << "-1\n";
        return;
    }
    num_type[EmptySelfLoop] += num_type[SplitPath];
    if (num_type[ComplexCycle] > 0) {
        if (num_type[EmptySelfLoop] < 2) {
            cout << "-1\n";
            return;
        }
    }
    // do the thing
    visited.assign(n + 1, false);
    for (auto [type, idx] : sources) {
        if (type == TrivialPath) trivial_component_contraction(idx);
    }
    for (auto [type, idx] : sources) {
        if (type == SplitPath || type == SplitCycle) with_top_contraction(idx);
        if (type == PerfectCycle) perfect_cycle_contraction(idx);
    }
    for (auto [type, idx] : sources) {
        if (type == ComplexCycle) with_top_contraction(idx);
    }
    // assert(req_moves == drives.size());
    cout << drives.size() << "\n";
    for (auto [u, v] : drives) cout << u + 1 << " " << v + 1 << "\n";
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    solve();
}

Compilation message

Main.cpp: In function 'int main()':
Main.cpp:230:9: warning: unused variable 't' [-Wunused-variable]
  230 |     int t = 1;
      |         ^
# Verdict Execution time Memory Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 344 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 344 KB Output is correct
8 Correct 0 ms 344 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 348 KB Output is correct
# Verdict Execution time Memory Grader output
1 Incorrect 53 ms 15968 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Correct 1 ms 348 KB Output is correct
4 Correct 1 ms 604 KB Output is correct
5 Correct 1 ms 348 KB Output is correct
6 Correct 0 ms 348 KB Output is correct
7 Correct 0 ms 604 KB Output is correct
8 Correct 0 ms 344 KB Output is correct
9 Correct 1 ms 604 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Correct 1 ms 348 KB Output is correct
4 Correct 1 ms 604 KB Output is correct
5 Correct 1 ms 348 KB Output is correct
6 Correct 0 ms 348 KB Output is correct
7 Correct 0 ms 604 KB Output is correct
8 Correct 0 ms 344 KB Output is correct
9 Correct 1 ms 604 KB Output is correct
10 Correct 136 ms 29744 KB Output is correct
11 Correct 64 ms 26236 KB Output is correct
12 Correct 83 ms 23992 KB Output is correct
13 Correct 136 ms 28348 KB Output is correct
14 Correct 78 ms 24636 KB Output is correct
15 Correct 89 ms 23612 KB Output is correct
16 Correct 151 ms 29996 KB Output is correct
17 Correct 83 ms 23612 KB Output is correct
18 Correct 129 ms 29372 KB Output is correct
# Verdict Execution time Memory Grader output
1 Incorrect 1 ms 348 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 344 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 344 KB Output is correct
8 Correct 0 ms 344 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 348 KB Output is correct
11 Incorrect 53 ms 15968 KB Output isn't correct
12 Halted 0 ms 0 KB -