Submission #233620

# Submission time Handle Problem Language Result Execution time Memory
233620 2020-05-21T05:41:01 Z dolphingarlic Islands (IOI08_islands) C++14
80 / 100
627 ms 131076 KB
/*
IOI 2008 Islands
- to, split the graph up into its connected components. We want the sum of the longest
  paths in each component
- Notice how each component is made of a single cycle with trees appended to each node on the cycle
- Case 1: The longest path lies in one of the trees
    - Just use DP to find this length
- Case 2: The longest path goes from one tree to the other and crosses the cycle
    - Let dp[i] = The length of the longest path going through node i
    - If we flatten the cycle by removing an edge, then notice how
      we can use prefix sums to get the answer in this case
- Just handle these 2 cases for each component
- Complexity: O(N)
*/

#include <bits/stdc++.h>
#define FOR(i, x, y) for (int i = x; i < y; i++)
typedef long long ll;
using namespace std;

struct Edge {
    int idx, to;
    ll len;

    bool operator!=(Edge B) { return idx != B.idx; }
};

vector<Edge> graph[1000001], cycle;
ll discarded, ans = 0, cmp_ans, p[5][1000001];
int cycle_start = 0;
bool processed[1000001], visited[1000001], on_cycle[1000001], adding = false;

void find_cycle(int node, Edge parent = {0, 0, 0}) {
    if (visited[node]) {
        cycle_start = node;
        cycle.push_back({0, node, 0});
        cycle.push_back(parent);
        adding = true;
        return;
    }
    visited[node] = true;
    for (Edge i : graph[node]) if (i != parent) {
        find_cycle(i.to, {i.idx, node, i.len});
        if (cycle_start) {
            if (node == cycle_start) adding = false;
            if (adding) cycle.push_back(parent);
            return;
        }
    }
}

void calc_tree(int node, int parent = 0) {
    processed[node] = true;
    ll mx = 0, sc = 0;
    for (Edge i : graph[node]) if (i.to != parent && !on_cycle[i.to]) {
        calc_tree(i.to, node);
        if (p[4][i.to] + i.len > mx) sc = mx, mx = p[4][i.to] + i.len;
        else if (p[4][i.to] + i.len > sc) sc = p[4][i.to] + i.len;
    }
    p[4][node] = mx;
    cmp_ans = max(cmp_ans, mx + sc);
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n;
    cin >> n;
    FOR(i, 1, n + 1) {
        int v;
        ll l;
        cin >> v >> l;
        graph[i].push_back({i, v, l});
        graph[v].push_back({i, i, l});
    }

    FOR(i, 1, n + 1) if (!processed[i]) {
        cycle.clear();
        cycle_start = 0;
        find_cycle(i);
        discarded = cycle.back().len;
        cycle.pop_back();

        for (Edge j : cycle) on_cycle[j.to] = true;

        cmp_ans = 0;

        FOR(j, 1, cycle.size()) p[0][cycle[j].to] = p[0][cycle[j - 1].to] + cycle[j].len;
        for (int j = cycle.size() - 2; j >= 0; j--)
            p[1][cycle[j].to] = p[1][cycle[j + 1].to] + cycle[j + 1].len;

        FOR(j, 0, cycle.size()) {
            calc_tree(cycle[j].to);
            p[2][cycle[j].to] = p[4][cycle[j].to] - p[0][cycle[j].to];
            p[3][cycle[j].to] = p[4][cycle[j].to] + p[0][cycle[j].to];
            p[4][cycle[j].to] = p[4][cycle[j].to] + p[1][cycle[j].to];
        }

        ll mx = 0;
        FOR(j, 0, cycle.size()) {
            cmp_ans = max(cmp_ans, p[3][cycle[j].to] + mx);
            mx = max(mx, p[2][cycle[j].to]);
        }
        mx = p[4][cycle.back().to];
        for (int j = cycle.size() - 2; j >= 0; j--) {
            cmp_ans = max(cmp_ans, p[3][cycle[j].to] + mx + discarded);
            mx = max(mx, p[4][cycle[j].to]);
        }

        ans += cmp_ans;
    }
    cout << ans;
    return 0;
}

Compilation message

islands.cpp: In function 'int main()':
islands.cpp:17:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, x, y) for (int i = x; i < y; i++)
islands.cpp:88:13:
         FOR(j, 1, cycle.size()) p[0][cycle[j].to] = p[0][cycle[j - 1].to] + cycle[j].len;
             ~~~~~~~~~~~~~~~~~~          
islands.cpp:88:9: note: in expansion of macro 'FOR'
         FOR(j, 1, cycle.size()) p[0][cycle[j].to] = p[0][cycle[j - 1].to] + cycle[j].len;
         ^~~
islands.cpp:17:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, x, y) for (int i = x; i < y; i++)
islands.cpp:92:13:
         FOR(j, 0, cycle.size()) {
             ~~~~~~~~~~~~~~~~~~          
islands.cpp:92:9: note: in expansion of macro 'FOR'
         FOR(j, 0, cycle.size()) {
         ^~~
islands.cpp:17:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define FOR(i, x, y) for (int i = x; i < y; i++)
islands.cpp:100:13:
         FOR(j, 0, cycle.size()) {
             ~~~~~~~~~~~~~~~~~~          
islands.cpp:100:9: note: in expansion of macro 'FOR'
         FOR(j, 0, cycle.size()) {
         ^~~
# Verdict Execution time Memory Grader output
1 Correct 18 ms 23808 KB Output is correct
2 Correct 17 ms 23936 KB Output is correct
3 Correct 19 ms 23936 KB Output is correct
4 Correct 17 ms 23808 KB Output is correct
5 Correct 17 ms 23808 KB Output is correct
6 Correct 18 ms 24064 KB Output is correct
7 Correct 18 ms 23936 KB Output is correct
8 Correct 18 ms 23936 KB Output is correct
9 Correct 17 ms 23808 KB Output is correct
10 Correct 19 ms 23936 KB Output is correct
11 Correct 17 ms 23936 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 18 ms 24064 KB Output is correct
2 Correct 17 ms 24064 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 18 ms 24064 KB Output is correct
2 Correct 19 ms 24448 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 25 ms 25600 KB Output is correct
2 Correct 39 ms 28916 KB Output is correct
3 Correct 29 ms 25856 KB Output is correct
4 Correct 24 ms 24952 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 47 ms 30576 KB Output is correct
2 Correct 62 ms 35056 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 104 ms 44400 KB Output is correct
2 Correct 127 ms 49000 KB Output is correct
3 Correct 141 ms 62020 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 185 ms 62572 KB Output is correct
2 Correct 236 ms 90080 KB Output is correct
3 Correct 252 ms 99292 KB Output is correct
4 Correct 345 ms 121172 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 370 ms 80320 KB Output is correct
2 Runtime error 627 ms 131076 KB Execution killed with signal 9 (could be triggered by violating memory limits)
3 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 441 ms 131076 KB Execution killed with signal 9 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -