Submission #272664

#TimeUsernameProblemLanguageResultExecution timeMemory
272664evpipisDuathlon (APIO18_duathlon)C++11
10 / 100
268 ms38764 KiB
#include <bits/stdc++.h> using namespace std; #define fi first #define se second #define pb push_back #define mp make_pair typedef pair<int, int> ii; typedef long long ll; const int len = 2e5+5; int num[len], low[len], art[len], sz[len], vis[len], par[len], subtree[len]; int cnt_dfs, cnt_com, n, m; ii edge[len]; vector<int> com[len], nex[len], stck; vector<ii> adj[len]; // this dfs works fine because the graph is simple // (no multiple edges or self loops) void dfs(int u, int root = 0){ num[u] = low[u] = ++cnt_dfs; int children = 0; for (auto v: adj[u]){ if (!vis[v.se] && !num[v.fi]){ children++; vis[v.se] = 1, stck.pb(v.se); dfs(v.fi); low[u] = min(low[u], low[v.fi]); if (low[v.fi] >= num[u]){ cnt_com++; art[u] = 1; while (true){ int e = stck.back(); stck.pop_back(); com[cnt_com].pb(e); if (e == v.se) break; } } } else if (!vis[v.se] && num[v.fi]){ vis[v.se] = 1, stck.pb(v.se); low[u] = min(low[u], num[v.fi]); } } if (root) art[u] = (children > 1); //printf("finished dfs: u = %d, art = %d, num = %d, low = %d\n", u, art[u], num[u], low[u]); } void decompose(){ set<ii> mys; for (int i = 1; i <= n; i++) vis[i] = 0; for (int i = 1; i <= cnt_com; i++){ /* printf("component $%d:", i); for (auto e: com[i]) printf(" (%d, %d)", edge[e].fi, edge[e].se); printf("\n"); */ for (auto e: com[i]){ int a = edge[e].fi, b = edge[e].se; if (!vis[a] && !art[a]) vis[a] = 1, sz[i+n]++; if (!art[b] && !vis[b]) vis[b] = 1, sz[i+n]++; if (art[a] && !mys.count(mp(a, i+n))){ mys.insert(mp(a, i+n)); nex[a].pb(i+n); nex[i+n].pb(a); } if (art[b] && !mys.count(mp(b, i+n))){ mys.insert(mp(b, i+n)); nex[b].pb(i+n); nex[i+n].pb(b); } } //printf("sz = %d\n", sz[i+n]); } } void fix(int u){ /* printf("u = %d\n", u); if (art[u]) printf("i am articulation point\n"); else printf("i am a 2-vertext cc\n"); */ subtree[u] = 1; if (!art[u]) subtree[u] = sz[u]; for (auto v: nex[u]){ if (v == par[u]) continue; par[v] = u; fix(v); subtree[u] += subtree[v]; } //printf("ins fix: u = %d, subtree = %d\n", u, subtree[u]); } ll solve(int u, int all){ //printf("u = %d, all = %d\n", u, all); ll ans = 0; for (auto v: nex[u]) if (v != par[u]) ans += solve(v, all); ll sum = 0; for (auto v: nex[u]){ int sub = subtree[v]; if (v == par[u]) sub = all-subtree[u]; //printf("%d -> %d, sub = %d\n", u, v, sub); sum += sub; } //printf("u = %d, sum = %lld\n", u, sum); if (art[u]){ for (auto v: nex[u]){ int sub = subtree[v]; if (v == par[u]) sub = all-subtree[u]; // two different subtrees ans += sub*1LL*(sum-sub); // same subtree - not all cases ans += sz[v]*1LL*(sz[v]-1); ans += 2*sz[v]*1LL*(sub-sz[v]); } } else{ int mul = 0; for (auto v: nex[u]){ int sub = subtree[v]; if (v == par[u]) sub = all-subtree[u]; mul += sub*1LL*(sum-sub); } for (auto v: nex[u]){ int sub = subtree[v]; if (v == par[u]) sub = all-subtree[u]; // two different subtrees ans += sz[u]*1LL*sub*1LL*(sum-sub); // 1 from my cc and one from a subtree ans += 2*sz[u]*1LL*(sz[u]-1)*1LL*sub; // 2 from my cc ans += sz[u]*1LL*(sz[u]-1)*1LL*(sz[u]-2); // center is adjacent art ans += mul - 2*sub*1LL*(sum-sub); } } return ans; } int main(){ scanf("%d %d", &n, &m); for (int i = 0; i < m; i++){ int a, b; scanf("%d %d", &a, &b); adj[a].pb(mp(b, i)); adj[b].pb(mp(a, i)); edge[i] = mp(a, b); } for (int i = 1; i <= n; i++) if (!num[i]) dfs(i, 1); //printf("after dfs\n"); decompose(); //printf("after decompose\n"); //printf("cnt_com = %d\n", cnt_com); ll ans = 0; for (int i = 1; i <= n+cnt_com; i++) if ((art[i] || i >= n+1) && !par[i]) fix(i), ans += solve(i, subtree[i]); //printf("after solve\n"); printf("%lld\n", ans); return 0; } /* 4 3 1 2 2 3 3 4 4 4 1 2 2 3 3 4 4 2 */

Compilation message (stderr)

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