답안 #963719

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
963719 2024-04-15T14:12:52 Z alextodoran 조이터에서 친구를 만드는건 재밌어 (JOI20_joitter2) C++17
0 / 100
5 ms 15012 KB
/**
 _  _   __  _ _ _  _  _ _
 |a  ||t  ||o    d | |o  |
| __    _| | _ | __|  _ |
| __ |/_  | __  /__\ / _\|

**/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N_MAX = 100000;

int N, M;

int root[N_MAX + 2];
int cnt[N_MAX + 2];
set <int> in[N_MAX + 2];
set <int> ins[N_MAX + 2];
set <pair <int, int>> out[N_MAX + 2];
ll answer;

ll f (int u) {
    return (ll) in[u].size() * cnt[u] + (ll) cnt[u] * (cnt[u] - 1);
}

int find_root (int u) {
    return (root[u] == 0 ? u : root[u] = find_root(root[u]));
}

queue <pair <int, int>> join_que;

void del_edge (int u, int v) {
    int ru = find_root(u), rv = find_root(v);
    in[rv].erase(u);
    out[ru].erase({u, rv});
}
bool add_edge (int u, int v) {
    int ru = find_root(u), rv = find_root(v);
    if (ru == rv || out[ru].find({u, rv}) != out[ru].end()) {
        return false;
    }
    in[rv].insert(u);
    out[ru].insert({u, rv});
    ins[rv].insert(ru);
    if (ins[ru].find(rv) != ins[ru].end()) {
        join_que.push({ru, rv});
    }
    return true;
}
void join (int u, int v) {
    if (u == v) {
        return;
    }
    if ((int) in[u].size() + (int) out[u].size()
      > (int) in[v].size() + (int) out[v].size()) {
        swap(u, v);
    }
    answer -= f(u) + f(v);
    vector <pair <int, int>> del, add;
    for (int x : in[u]) {
        del.push_back({x, u});
        if (find_root(x) != v) {
            add.push_back({x, u});
        }
    }
    for (pair <int, int> e : out[u]) {
        del.push_back(e);
        if (e.second != v) {
            add.push_back(e);
        }
    }
    for (pair <int, int> e : del) {
        del_edge(e.first, e.second);
    }
    root[u] = v;
    cnt[v] += cnt[u];
    for (pair <int, int> e : add) {
        add_edge(e.first, e.second);
    }
    answer += f(v);
}

int main () {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    cin >> N >> M;
    fill(cnt + 1, cnt + N + 1, 1);
    while (M--) {
        int u, v;
        cin >> u >> v;
        if (add_edge(u, v) == true) {
            answer += cnt[find_root(v)];
        }
        while (join_que.empty() == false) {
            pair <int, int> e = join_que.front();
            join_que.pop();
            join(e.first, e.second);
        }
        cout << answer << "\n";
    }

    return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 3 ms 14940 KB Output is correct
2 Correct 5 ms 14940 KB Output is correct
3 Correct 3 ms 14940 KB Output is correct
4 Correct 3 ms 14940 KB Output is correct
5 Correct 4 ms 14940 KB Output is correct
6 Correct 3 ms 14788 KB Output is correct
7 Correct 4 ms 15012 KB Output is correct
8 Incorrect 4 ms 14940 KB Output isn't correct
9 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 3 ms 14940 KB Output is correct
2 Correct 5 ms 14940 KB Output is correct
3 Correct 3 ms 14940 KB Output is correct
4 Correct 3 ms 14940 KB Output is correct
5 Correct 4 ms 14940 KB Output is correct
6 Correct 3 ms 14788 KB Output is correct
7 Correct 4 ms 15012 KB Output is correct
8 Incorrect 4 ms 14940 KB Output isn't correct
9 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 3 ms 14940 KB Output is correct
2 Correct 5 ms 14940 KB Output is correct
3 Correct 3 ms 14940 KB Output is correct
4 Correct 3 ms 14940 KB Output is correct
5 Correct 4 ms 14940 KB Output is correct
6 Correct 3 ms 14788 KB Output is correct
7 Correct 4 ms 15012 KB Output is correct
8 Incorrect 4 ms 14940 KB Output isn't correct
9 Halted 0 ms 0 KB -