Submission #267068

#TimeUsernameProblemLanguageResultExecution timeMemory
267068ChrisTMountains and Valleys (CCO20_day1problem3)C++17
21 / 25
7066 ms185788 KiB
#include <bits/stdc++.h> using namespace std; using pii = pair<int,int>; using ll = long long; #define all(x) (x).begin(),(x).end() const int MN = 5e5+4, MOD = 998244353, BASE = 31; vector<int> adj[MN]; struct Edge { int a,b,w; }; int sum, diam, ret, n, subREE[MN], down[MN], down2[MN], pp[MN], which[MN], up[MN], cc, comp[MN], sz[MN], depth[MN], subDiam[MN], wotDown[MN][2], wotDiam[MN], valDown[MN][3], valDiam[MN][2], case1[MN], case2[MN], case3[MN], upDiam[MN]; bool done[MN]; ll iters; void dfs (int cur, int par = -1) { down[cur] = down2[cur] = 0; for (int i : adj[cur]) if (i != par) { dfs(i,cur); ++sum; int d = down[i] + 1; if (d > down[cur]) { down2[cur] = down[cur]; down[cur] = d; } else down2[cur] = max(down2[cur],d); } diam = max(diam,down[cur] + down2[cur]); } void dfs3 (int cur, int par = -1) { pp[cur] = par; if (~par) up[cur] = max(up[par],cur == wotDown[par][0] ? valDown[par][1] : valDown[par][0]) + 1; else up[cur] = 0; for (int i : adj[cur]) if (i != par) { dfs3(i,cur); } } int solve (int rt) { sum = 0; diam = 0; dfs(rt); return sum * 2 - diam; } int getsz (int cur, int par = -1) { sz[cur] = 1; for (int i : adj[cur]) if (i != par && !done[i]) { sz[cur] += getsz(i,cur); } return sz[cur]; } int getcent (int cur, int tot, int par = -1) { for (int i : adj[cur]) if (i != par && !done[i] && sz[i] > (tot>>1)) return getcent(i,tot,cur); return cur; } void godown (int cur, int par) { depth[cur] = depth[par] + 1; valDown[cur][0]=valDown[cur][1]=valDown[cur][2]=valDiam[cur][0]=valDiam[cur][1]=0; comp[cur] = cc; for (int i : adj[cur]) if (i != par) { int d,dia,who; if (!done[i]) { godown(i,cur); dia = subDiam[i]; d = valDown[i][0] + 1; who = i; } else { if (pp[i] == cur) { dia = subREE[i]; d = down[i] + 1; } else { d = up[cur]; dia = upDiam[cur]; } who = -1; } if (d > valDown[cur][0]) { valDown[cur][2] = valDown[cur][1]; valDown[cur][1] = valDown[cur][0]; valDown[cur][0] = d; wotDown[cur][1] = wotDown[cur][0]; wotDown[cur][0] = who; } else if (d > valDown[cur][1]) { valDown[cur][2] = valDown[cur][1]; valDown[cur][1] = d; wotDown[cur][1] = who; } else valDown[cur][2] = max(valDown[cur][2],d); if (dia > valDiam[cur][0]) { valDiam[cur][1] = valDiam[cur][0]; valDiam[cur][0] = dia; wotDiam[cur] = who; } else valDiam[cur][1] = max(valDiam[cur][1],dia); } subDiam[cur] = max(valDiam[cur][0],valDown[cur][0] + valDown[cur][1]); } void goup (int cur, int par = -1, int push = 0, int push2 = 0) { case1[cur] = max(push,subDiam[cur]); case2[cur] = max(push2,valDown[cur][0]); for (int i : adj[cur]) if (i != par && !done[i]) { bool go = i == wotDown[cur][0]; int direct = valDown[cur][go] + valDown[cur][1 + (go || i == wotDown[cur][1])]; int indirect = valDiam[cur][i == wotDiam[cur]]; int togo = valDown[cur][go]; case3[i] = max(case3[cur],togo+depth[cur]); goup(i,cur,max({push,indirect,direct}),max(push2,togo) + 1); } } void prep (int cur, int par = -1, int push = 0) { upDiam[cur] = push; subREE[cur] = subDiam[cur]; push = max(push,up[cur]); for (int i : adj[cur]) if (i != par) { bool go = i == wotDown[cur][0]; int direct = valDown[cur][go] + valDown[cur][1 + (go || i == wotDown[cur][1])]; int indirect = valDiam[cur][i == wotDiam[cur]]; int whoops = valDown[cur][go] + up[cur]; prep(i,cur,max({push,whoops,direct,indirect})); } } void solve (int cur, vector<Edge> &queries) { int cent = getcent(cur,getsz(cur)); cc = 0; vector<pii> diams, downs; depth[cent] = 0; done[cent] = 1; case2[cent] = 0; for (int i : adj[cent]) { if (!done[i]) { godown(i,cent); case3[i] = 0; goup(i,cent,0); diams.emplace_back(subDiam[i],cc); downs.emplace_back(valDown[i][0] + 1, cc); ++cc; } else { if (pp[i] == cent) { diams.emplace_back(subREE[i],-1); downs.emplace_back(down[i] + 1, -1); } else { downs.emplace_back(up[cent], -1); diams.emplace_back(upDiam[cent],-1); } } } sort(diams.rbegin(),diams.rend()); sort(downs.rbegin(),downs.rend()); vector<vector<Edge>> togo(cc); for (Edge q : queries) { if (q.a == cent || q.b == cent) { if (q.a == cent) swap(q.a,q.b); int direct = 0, cnt = 0, best = 0; for (pii p : downs) if (p.second != comp[q.a]) { ++cnt; direct += p.first; if (cnt == 2) break; best = p.first; } int indirect = 0; for (pii p : diams) if (p.second != comp[q.a]) { indirect = p.first; break; } int len = max({direct,indirect,case1[q.a]}); int cyc = q.w + depth[q.a]; cnt = n - 1 - depth[q.a]; ret = min(ret,cnt * 2 + cyc - len); int yeet = q.w + max({case2[q.a]+case2[q.b],depth[q.a]+best+case2[q.b],case2[q.a]+best+depth[q.b]}); ret = min(ret,(n - 2 + q.w) * 2 - yeet); } else if (comp[q.a] == comp[q.b]) togo[comp[q.a]].push_back(q); else { int direct = 0, cnt = 0, best = 0; for (pii p : downs) if (p.second != comp[q.a] && p.second != comp[q.b]) { ++cnt; direct += p.first; if (cnt == 2) break; best = p.first; } int indirect = 0; for (pii p : diams) if (p.second != comp[q.a] && p.second != comp[q.b]) { indirect = p.first; break; } int len = max({direct,indirect,case1[q.a],case1[q.b]}); int cyc = q.w + depth[q.a] + depth[q.b]; cnt = n - 1 - depth[q.a] - depth[q.b]; ret = min(ret,cnt * 2 + cyc - len); int yeet = q.w + max({case2[q.a]+case2[q.b],depth[q.a]+best+case2[q.b],case2[q.a]+best+depth[q.b],case3[q.a]+valDown[q.a][0]+depth[q.b],case3[q.b]+valDown[q.b][0]+depth[q.a]}); ret = min(ret,(n - 2 + q.w) * 2 - yeet); } } int oh = 0; for (int i : adj[cent]) if (!done[i]) { solve(i,togo[oh]); ++oh; } } int main () { int m; scanf ("%d %d",&n,&m); vector<Edge> extra; while (m--) { int a,b,w; scanf ("%d %d %d",&a,&b,&w); ++a; ++b; if (w>1) extra.push_back({a,b,w}); else adj[a].push_back(b), adj[b].push_back(a); } ret = solve(1); godown(1,0); dfs3(1); goup(1); prep(1); solve(1,extra); printf ("%d\n",ret); return 0; }

Compilation message (stderr)

Main.cpp: In function 'int main()':
Main.cpp:177:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  177 |  scanf ("%d %d",&n,&m);
      |  ~~~~~~^~~~~~~~~~~~~~~
Main.cpp:181:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  181 |   scanf ("%d %d %d",&a,&b,&w); ++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...