제출 #236931

#제출 시각아이디문제언어결과실행 시간메모리
236931Lucina철인 이종 경기 (APIO18_duathlon)C++17
18 / 100
1093 ms45264 KiB
#include<bits/stdc++.h> using namespace std; int const nax = 2e5 + 10; struct DSU { int par[nax]; int sz[nax]; int n; DSU (int n) { this->n = n; iota(par + 1, par + 1 + n, 1); fill(sz + 1, sz + 1 + n, 1); } int find (int x) { return x == par[x] ? x : par[x] = find(par[x]); } bool unite (int x, int y) { x = find(x), y = find(y); if (x == y) return false; if (sz[x] < sz[y]) swap(x, y); sz[x] += sz[y]; par[y] = x; return true; } }; int n, m; vector <pair <int, int>> e; vector <pair <int, int>> a[nax]; vector <int> bridge_id; int tin[nax], timer, low[nax]; int sz[nax]; vector <int> b[nax]; vector <int> comp_node; long long ans ; bool vis[nax]; int sub_sz[nax]; long long all_subtract; vector <int> important_node[nax]; vector <int> to_convolve[nax]; long long C (long long v) { return v * (v - 1) * (v - 2); } int dfs_tree_sz (int nod, int from) { sub_sz[nod] = sz[nod]; vis[nod] = true; for (int i : b[nod]) { if (i != from) { sub_sz[nod] += dfs_tree_sz(i, nod); } } return sub_sz[nod]; } void dfs_triplet (int nod, int from, int tree_sz) { for (int i : b[nod]) { /// if (i == from) continue; ans -= 1LL * sz[nod] * sub_sz[i] * (sub_sz[i] - 1); // all_subtract += 1LL * sz[nod] * sub_sz[i] * (sub_sz[i] - 1); ans -= 2LL * (sz[nod] - 1) * sub_sz[i]; // all_subtract += 2LL * (sz[nod] - 1) * sub_sz[i]; // fprintf(stderr, "subtract %lld\n", 2LL * (sz[nod] - 1) * sub_sz[i]); /// fprintf(stderr, "subtraction size nod and sub %d %d\n", sz[nod], sub_sz[i]); } for (int im_nod : important_node[nod]) { /** */ long long square_sum = 0; long long simple_sum = 0; for (int con : to_convolve[im_nod]) { square_sum += 1LL * sub_sz[con] * sub_sz[con]; simple_sum += sub_sz[con]; } long long tot = (simple_sum * simple_sum - square_sum) / 2; ans -= tot * (sz[nod] - 1); } for (int i : b[nod]) { if (i != from) { int pre_sub_sz_nod = sub_sz[nod]; int pre_sub_sz_i = sub_sz[i]; sub_sz[i] = tree_sz; sub_sz[nod] = tree_sz - pre_sub_sz_i; dfs_triplet(i, nod, tree_sz); sub_sz[nod] = pre_sub_sz_nod; sub_sz[i] = pre_sub_sz_i; } } } int main () { scanf("%d %d", &n, &m); e.resize(m); int ct = 0; for (auto &edge : e) { scanf("%d %d", &edge.first, &edge.second); a[edge.first].emplace_back(edge.second, ct); a[edge.second].emplace_back(edge.first, ct); ++ ct; } DSU ds(n); fill(vis + 1, vis + 1 + n, false); function <void(int, int)> dfs_scc = [&] (int node, int from_edge) ->void { vis[node] = true; tin[node] = low[node] = ++ timer; for (auto [i, j] : a[node]) { if (!vis[i]) { dfs_scc(i, j); low[node] = min(low[node], low[i]); if (low[i] > tin[node]) { bridge_id.push_back(j); } } else if (j != from_edge) { /// ds.unite(node, i); low[node] = min(low[node], tin[i]); } } }; for (int i = 1 ; i <= n ; ++ i) { if (!vis[i]) { dfs_scc(i, -1); } } set <int> setik; for (int i = 0 ;i < m ; ++ i) setik.insert(i); for (int i : bridge_id) setik.erase(setik.find(i)); for (int i : setik) { ds.unite(e[i].first, e[i].second); } for (int i : bridge_id) { int u = ds.find(e[i].first); int v = ds.find(e[i].second); int sz_u = ds.sz[u]; int sz_v = ds.sz[v]; sz[u] = sz_u; sz[v] = sz_v; b[u].push_back(v); b[v].push_back(u); // fprintf(stderr, "Edge %d %d\n", u, v); // fprintf(stderr, "%d %d\n", sz[u], sz[v]); comp_node.push_back(u); comp_node.push_back(v); important_node[u].push_back(e[i].first); important_node[v].push_back(e[i].second); to_convolve[e[i].first].push_back(v); to_convolve[e[i].second].push_back(u); } fill(vis + 1, vis + 1 + n, false); for (int i : comp_node) { if (!vis[i]) { int tree_sz = dfs_tree_sz(i, 0); ans += C(tree_sz); dfs_triplet(i, 0, tree_sz); } } for (int i = 1 ;i <= n ; ++ i) { int comp = ds.find(i); if (vis[comp]) continue; vis[comp] = true; ans += C(ds.sz[comp]); } // fprintf(stderr, "all subtract %lld\n", all_subtract); printf("%lld\n", ans); } /** 4 3 1 2 2 3 3 4 */

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

count_triplets.cpp: In function 'int main()':
count_triplets.cpp:111:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d %d", &n, &m);
     ~~~~~^~~~~~~~~~~~~~~~~
count_triplets.cpp:117:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d %d", &edge.first, &edge.second);
         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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...