답안 #364643

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
364643 2021-02-09T16:20:47 Z valerikk 조이터에서 친구를 만드는건 재밌어 (JOI20_joitter2) C++17
0 / 100
11 ms 14444 KB
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5 + 7;

int n, m;
ll res;
int p[N], sz[N];
set<int> out[N], in[N];
set<int> st[N];

int Find(int node) {
    if(p[node] == node) return node;
    p[node] = Find(p[node]);
    return p[node];
}

void AddEdge(int a, int b) {
    if(Find(a) == Find(b) || out[a].find(Find(b)) != out[a].end()) return;
    //printf("Edge added: %d %d\n", a, Find(b));
    out[a].insert(Find(b));
    in[Find(b)].insert(a);
    res += sz[b];
}

void RemoveEdge(int a, int b) {
    //if(Find(a) == Find(b) || out[a].find(Find(b)) == out[a].end()) return;
    //printf("Edge removed: %d %d\n", a, Find(b));
    out[a].erase(Find(b));
    in[Find(b)].erase(a);
    res -= sz[Find(b)];
}

bool Union(int a, int b) {
    a = Find(a);
    b = Find(b);
    if(a == b) return false;
    if(sz[a] > sz[b]) swap(a, b);
    bool ab = false, ba = false;
    for(int v: st[a]) ab |= in[b].find(v) != in[b].end();
    for(int v: in[a]) ba |= st[b].find(v) != st[b].end();
    if(!ab || !ba) return false;
    //printf("Union: %d %d\n", a, b);
    vector<pair<int, int> > rem;
    //printf("Removed edges\n");
    for(int v: st[a]) {
        if(out[v].find(b) != out[v].end()) rem.push_back({v, b});
    }
    for(int v: in[a]) {
        if(st[b].find(v) != st[b].end()) rem.push_back({v, a});
    }
    //for(auto& e: rem) printf("%d %d\n", e.first, e.second);
    for(auto& e: rem) RemoveEdge(e.first, e.second);
    res += 2ll * sz[a] * sz[b];
    //if (a == 4 && b == 2) printf("Union 4 2, res = %lld\n", res);
    res += 1ll * in[b].size() * sz[a];
    vector<int> vnext;
    for(int v: in[a]) {
        out[v].erase(a);
        out[v].insert(b);
        vnext.push_back(v);
        if(in[b].find(v) == in[b].end()){
            //printf("Redirect %d -> %d to %d\n", v, a, b);
            in[b].insert(v);
            res += sz[b];
        } else res -= sz[a];
    }
    in[a] = {};
    for(int v: st[a]){
        for(int to: out[v]) vnext.push_back(to);
        st[b].insert(v);
    }
    st[a] = {};
    sz[b] += sz[a];
    p[a] = b;
    for(int v: vnext) Union(v, b);
    return true;
}

void Init() {
    res = 0;
    for(int i = 1; i <= n; i++) {
        p[i] = i;
        sz[i] = 1;
        out[i] = in[i] = {};
        st[i] = {i};
    }
}

int main() {
    scanf("%d%d", &n, &m);
    Init();
    for(int day = 1; day <= m; day++) {
        int a, b;
        scanf("%d%d", &a, &b);
        //printf("%d -> %d, add = %d\n", a, b, sz[b]);
        AddEdge(a, b);
        Union(a, b);
        printf("%lld\n", res);
        //printf("After day %d\n", day);
        //for(int i = 1; i <= n; i++) printf("p[%d] = %d, sz[%d] = %d\n", i, p[i], i, sz[i]); 
    }
    return 0;
}

Compilation message

joitter2.cpp: In function 'int main()':
joitter2.cpp:91:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   91 |     scanf("%d%d", &n, &m);
      |     ~~~~~^~~~~~~~~~~~~~~~
joitter2.cpp:95:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   95 |         scanf("%d%d", &a, &b);
      |         ~~~~~^~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 14444 KB Output is correct
2 Incorrect 11 ms 14444 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 14444 KB Output is correct
2 Incorrect 11 ms 14444 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 14444 KB Output is correct
2 Incorrect 11 ms 14444 KB Output isn't correct
3 Halted 0 ms 0 KB -