Submission #1353641

#TimeUsernameProblemLanguageResultExecution timeMemory
1353641cnam9Pipes (CEOI15_pipes)C++20
100 / 100
391 ms3176 KiB
#include <iostream>

#include <vector>
#include <set>

#include <algorithm>
#include <numeric>

using namespace std;

constexpr int N = 1e5;

template <class T, size_t N>
class BufferedContainer {
    T buf[N];
    T *top = buf;

public:

    void push_back(T value) { *top++ = value; }
    void clear() { top = buf; }
    T *begin() { return buf; }
    T *end() { return top; }
};

int parent[N];
int sizeCC[N];
int parentCC[N];
int parent2CC[N];
// set<pair<int, int>> bridges;
int visted_token;
int visited[N];
BufferedContainer<int, N> pathA, pathB;
pair<int, int> bridge[N];

int find2CC(int v) {
    if (v == -1)
        return -1;
    return parent2CC[v] == v ? v : parent2CC[v] = find2CC(parent2CC[v]);
}

int findCC(int v) {
    v = find2CC(v);
    return parentCC[v] == v ? v : parentCC[v] = findCC(parentCC[v]);
}

void make_root(int v) {
    v = find2CC(v);
    int root = v;
    int child = -1;

    pair<int, int> current = {-1, -1};

    while (v != -1) {
        int p = find2CC(parent[v]);

        swap(current, bridge[v]);

        parent[v] = child;
        parentCC[v] = root;
        child = v;
        v = p;
    }
    sizeCC[root] = sizeCC[child];
}

void merge_path(int a, int b) {
    pathA.clear();
    pathB.clear();

    int lca = -1;
    visted_token++;

    while (lca == -1) {
        if (a != -1) {
            a = find2CC(a);
            pathA.push_back(a);

            if (visited[a] == visted_token) {
                lca = a;
                break;
            }

            visited[a] = visted_token;
            a = parent[a];
        }
        if (b != -1) {
            b = find2CC(b);
            pathB.push_back(b);

            if (visited[b] == visted_token) {
                lca = b;
                break;
            }

            visited[b] = visted_token;
            b = parent[b];
        }

    }

    for (int v : pathA) {
        parent2CC[v] = lca;
        if (v == lca) break;
        // cout << "bridge -= " << bridge[v].first << ' ' << bridge[v].second << " at " << v << endl;
        bridge[v].first = -1;
        // bridges.erase(minmax(v, parent[v]));
    }
    for (int v : pathB) {
        parent2CC[v] = lca;
        if (v == lca) break;
        // cout << "bridge -= " << bridge[v].first << ' ' << bridge[v].second << " at " << v << endl;
        bridge[v].first = -1;
        // bridges.erase(minmax(v, parent[v]));
    }
}

void add_edge(int u, int v) {
    int a = find2CC(u);
    int b = find2CC(v);
    if (a == b) return;

    int ca = findCC(a);
    int cb = findCC(b);

    if (ca == cb) {
        merge_path(a, b);
        return;
    }
    // bridges.insert(minmax(u, v));
    if (sizeCC[ca] > sizeCC[cb]) {
        swap(a, b);
        swap(ca, cb);
    }
    make_root(a);
    bridge[a] = {u, v};
    parent[a] = parentCC[a] = b;
    sizeCC[cb] += sizeCC[a];
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // freopen("input.txt", "r", stdin);

    int n, m;
    cin >> n >> m;

    fill(parent, parent + n, -1);
    iota(parent2CC, parent2CC + n, 0);
    iota(parentCC, parentCC + n, 0);
    fill(sizeCC, sizeCC + n, 1);
    fill(bridge, bridge + n, pair<int, int>{-1, -1});

    while (m--) {
        int u, v;
        cin >> u >> v;

        add_edge(u - 1, v - 1);
    }

    // for (auto [u, v] : bridges) {
    //     cout << u + 1 << ' ' << v + 1 << '\n';
    // }

    for (int u = 0; u < n; u++) {
        if (bridge[u].first == -1) continue;
        cout << bridge[u].first + 1 << ' ' << bridge[u].second + 1 << '\n';
    }

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