Submission #1044170

# Submission time Handle Problem Language Result Execution time Memory
1044170 2024-08-05T07:48:17 Z 우민규(#11006) Parking (CEOI22_parking) C++17
50 / 100
135 ms 30500 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 {
            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 {
            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 (!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] = b;
        
        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

In file included from /usr/include/c++/10/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/10/bits/stdc++.h:33,
                 from Main.cpp:1:
Main.cpp: In function 'void solve()':
Main.cpp:221:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  221 |     assert(req_moves == drives.size());
      |            ~~~~~~~~~~^~~~~~~~~~~~~~~~
Main.cpp: In function 'int main()':
Main.cpp:228:9: warning: unused variable 't' [-Wunused-variable]
  228 |     int t = 1;
      |         ^
# Verdict Execution time Memory Grader output
1 Correct 1 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 0 ms 348 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 348 KB Output is correct
7 Correct 0 ms 344 KB Output is correct
8 Correct 0 ms 348 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 Runtime error 53 ms 30500 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 504 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 600 KB Output is correct
5 Correct 0 ms 344 KB Output is correct
6 Correct 0 ms 348 KB Output is correct
7 Correct 1 ms 604 KB Output is correct
8 Correct 1 ms 348 KB Output is correct
9 Correct 1 ms 604 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 1 ms 504 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 1 ms 600 KB Output is correct
5 Correct 0 ms 344 KB Output is correct
6 Correct 0 ms 348 KB Output is correct
7 Correct 1 ms 604 KB Output is correct
8 Correct 1 ms 348 KB Output is correct
9 Correct 1 ms 604 KB Output is correct
10 Correct 135 ms 29688 KB Output is correct
11 Correct 56 ms 26044 KB Output is correct
12 Correct 81 ms 23864 KB Output is correct
13 Correct 115 ms 28352 KB Output is correct
14 Correct 82 ms 24628 KB Output is correct
15 Correct 69 ms 23740 KB Output is correct
16 Correct 128 ms 29876 KB Output is correct
17 Correct 72 ms 23444 KB Output is correct
18 Correct 117 ms 29376 KB Output is correct
# Verdict Execution time Memory Grader output
1 Runtime error 1 ms 856 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 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 0 ms 348 KB Output is correct
5 Correct 0 ms 348 KB Output is correct
6 Correct 0 ms 348 KB Output is correct
7 Correct 0 ms 344 KB Output is correct
8 Correct 0 ms 348 KB Output is correct
9 Correct 0 ms 348 KB Output is correct
10 Correct 0 ms 348 KB Output is correct
11 Runtime error 53 ms 30500 KB Execution killed with signal 6
12 Halted 0 ms 0 KB -