Submission #781247

#TimeUsernameProblemLanguageResultExecution timeMemory
781247Programmer123Islands (IOI08_islands)C++17
70 / 100
319 ms131072 KiB
#pragma GCC optimize("O3") #include <bits/stdc++.h> #define int long long int signed dest[1000000]; signed length[1000000]; std::vector<signed> backEdges[1000000]; std::bitset<1000000> seen; int bestPath[1000000]; #ifdef LOCAL #define debug std::cout #else #define debug std::stringstream() #endif void findComponent(signed node, std::vector<signed> &data) { if (seen[node]) return; data.push_back(node); seen[node] = true; findComponent(dest[node], data); for (auto x: backEdges[node]) { findComponent(x, data); } } int treeSum(int node) { int sum = 0; for (auto x: backEdges[node]) { if (!seen[x]) { sum += length[x] + treeSum(x); } } return sum; } int bestSingle(int node) { if (bestPath[node] != 0) { return bestPath[node]; } int best = 0; for (auto x: backEdges[node]) { if (!seen[x]) { best = std::max(best, length[x] + bestSingle(x)); } } return bestPath[node] = best; } int bestDouble(int node) { int best = 0; int secondBest = 0; std::vector<int> back; for (auto x: backEdges[node]) { if (!seen[x]) { int score = length[x] + bestSingle(x); if (score > best) { secondBest = best; best = score; } else if (score > secondBest) { secondBest = score; } } } return best + secondBest; } //Best score, assuming doesn't pass through edge between start and end of cycle. int bestA(signed root, signed cyclesize) { int best = 0; int current = 0; int bestBehind = 0; for (int i = 0; i < cyclesize; ++i) { best = std::max(best, bestSingle(root) + current + bestBehind); bestBehind = std::max(bestBehind, bestSingle(root) - current); current += length[root]; root = dest[root]; } return best; } int prev(int node) { for (auto x: backEdges[node]) { if (seen[x]) return x; } assert(false); } //Best score, assuming passes through edge between start and end of cycle int bestB(signed root, signed cyclesize) { int current = 0; // std::vector<int> lengthForward; // for (int i = 0; i < cycle.size() - 1; ++i) { // lengthForward.push_back(current); // current += length[cycle[i]]; // } current = 0; std::vector<int> lengthBackward; int node = prev(prev(root)); for (int i = 0; i < cyclesize - 1; ++i) { lengthBackward.push_back(current); current += length[node]; lengthBackward[i] += bestSingle(dest[node]); node = prev(node); } // node = prev(root); // for (int i = 0; i < cyclesize - 1; ++i) { // //lengthForward[i] += bestSingle(cycle[i]); // lengthBackward[i] += bestSingle(node); // node = prev(node); // } for (int i = 1; i < cyclesize - 1; ++i) { //lengthForward[i] = std::max(lengthForward[i], lengthForward[i - 1]); lengthBackward[i] = std::max(lengthBackward[i], lengthBackward[i - 1]); } int best = 0; int lengthForward = length[prev(root)]; int bestForward = lengthForward + bestSingle(root); for (int i = 0; i < cyclesize - 1; ++i) { best = std::max(best, bestForward + lengthBackward[cyclesize - 2 - i]); lengthForward += length[root]; bestForward = std::max(bestForward, lengthForward + bestSingle(root = dest[root])); } return best; } int componentSum(const std::vector<signed> &component) { for (auto x: component) { seen[x] = false; } signed root = component[0]; while (!seen[root]) { seen[root] = true; root = dest[root]; } for (auto x: component) { seen[x] = false; } signed cyclesize = 1; seen[root] = true; for (int x = dest[root]; x != root; x = dest[x]) { cyclesize++; seen[x] = true; } int best = 0; for (auto x: component) { best = std::max({best, bestDouble(x), bestSingle(x)}); } best = std::max(best, bestA(root, cyclesize)); best = std::max(best, bestB(root, cyclesize)); for (auto x: component) { seen[x] = true; } return best; } signed main() { #ifdef LOCAL freopen("INPUT", "r", stdin); #endif std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); int N; std::cin >> N; //seen = new bool[N]; for (signed i = 0; i < N; ++i) { seen[i] = false; signed x, l; std::cin >> x >> l; x--; dest[i] = x; length[i] = l; backEdges[x].push_back(i); } int total = 0; for (int i = 0; i < N; ++i) { if (!seen[i]) { std::vector<signed> component; findComponent(i, component); total += componentSum(component); } } std::cout << total << std::endl; }
#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...