답안 #1044182

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1044182 2024-08-05T07:53:32 Z 우민규(#11006) Parking (CEOI22_parking) C++17
50 / 100
208 ms 30348 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;
      |         ^
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 344 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 0 ms 344 KB Output is correct
4 Correct 0 ms 348 KB Output is correct
5 Correct 0 ms 344 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 348 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 344 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Runtime error 57 ms 30348 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 348 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 1 ms 344 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 1 ms 600 KB Output is correct
8 Correct 1 ms 348 KB Output is correct
9 Correct 1 ms 604 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 348 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 1 ms 344 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 1 ms 600 KB Output is correct
8 Correct 1 ms 348 KB Output is correct
9 Correct 1 ms 604 KB Output is correct
10 Correct 207 ms 29756 KB Output is correct
11 Correct 69 ms 26136 KB Output is correct
12 Correct 113 ms 23944 KB Output is correct
13 Correct 208 ms 28352 KB Output is correct
14 Correct 74 ms 24608 KB Output is correct
15 Correct 85 ms 23668 KB Output is correct
16 Correct 152 ms 29916 KB Output is correct
17 Correct 71 ms 23608 KB Output is correct
18 Correct 146 ms 29368 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1 ms 860 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 344 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 0 ms 344 KB Output is correct
4 Correct 0 ms 348 KB Output is correct
5 Correct 0 ms 344 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 0 ms 348 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 344 KB Output is correct
11 Runtime error 57 ms 30348 KB Execution killed with signal 6
12 Halted 0 ms 0 KB -