제출 #364651

#제출 시각아이디문제언어결과실행 시간메모리
364651valerikk조이터에서 친구를 만드는건 재밌어 (JOI20_joitter2)C++17
100 / 100
1404 ms59884 KiB
#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[Find(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); 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]; out[v].insert(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() { #ifdef LOCAL freopen("D:/cp/tmp/input.txt", "r", stdin); #endif 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); /*if(day == 6) { printf("res: %lld\n", res); printf("4: "); for(int v: st[4]) printf("%d ", v); printf("\n2: "); for(int v: st[2]) printf("%d ", v); printf("\n4: "); for(int v: in[4]) printf("%d ", v); printf("\n2: "); for(int v: in[2]) printf("%d ", v); }*/ 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; }

컴파일 시 표준 에러 (stderr) 메시지

joitter2.cpp: In function 'int main()':
joitter2.cpp:94:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   94 |     scanf("%d%d", &n, &m);
      |     ~~~~~^~~~~~~~~~~~~~~~
joitter2.cpp:98:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   98 |         scanf("%d%d", &a, &b);
      |         ~~~~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...