公式

C - ネットワークの通信コスト / Network Communication Cost 解説 by admin

Claude 4.6 Opus (Thinking)

Overview

This is a simulation problem on a tree-structured network where you switch the operating modes of relay stations and update correction parameters, while calculating the communication cost along the path between two specified points.

Analysis

  • In a tree structure, the path between any two vertices \(A\) and \(B\) is uniquely determined. We simply need to find that path and calculate the communication cost.
  • Since the constraints are relatively small with \(N \leq 5000\) and \(Q \leq 5000\), recomputing the path for each query is fast enough.
  • The effective coordinates of each relay station are either \((X_i, Y_i)\) or \((-X_i, -Y_i)\) depending on the operating mode, so we need to reference the mode at the time of the query for computation.
  • Advanced data structures (such as Heavy-Light Decomposition) are unnecessary; a straightforward approach of finding the path with BFS and summing up the cost for each edge is sufficient.

Algorithm

  1. Reading input and initialization: Read the coordinates of each relay station and the tree edge information. Initialize all relay stations to normal mode with \(S = 0\).

  2. Operation 1 (1 C): Toggle the operating mode flag of relay station \(C\).

  3. Operation 2 (2 W): Add \(W\) to \(S\).

  4. Operation 3 (3 A B): Compute the answer with the following procedure:

    • If \(A = B\), there is 1 relay station on the path and 0 links, so the answer is \(S \times 1 = S\).
    • If \(A \neq B\), find the path from \(A\) to \(B\) using BFS. Specifically, record parent information during BFS and reconstruct the path by tracing parents from \(B\) back to \(A\).
    • For each adjacent pair of relay stations \((u, v)\) on the path, compute the Manhattan distance \(|X'_u - X'_v| + |Y'_u - Y'_v|\) using the effective coordinates based on the current operating mode, and take the total sum.
    • The final answer is “total communication cost \(+\) \(S \times\) number of relay stations on the path”.

Complexity

  • Time complexity: \(O(Q \times N)\)
    • Each operation 3 performs BFS (\(O(N)\)) and cost calculation along the path (\(O(N)\)). Operations 1 and 2 are \(O(1)\).
    • In the worst case with \(Q = 5000\) and \(N = 5000\), the computation is approximately \(2.5 \times 10^7\).
  • Space complexity: \(O(N)\)
    • \(O(N)\) for the adjacency list, parent array, path array, etc.

Implementation Notes

  • Manage a parent array parent during BFS, recording parent[v] = u (the vertex \(u\) that discovered \(v\)). Set parent[A] = A for the starting point \(A\) to distinguish it from unvisited vertices.

  • Path reconstruction is done by tracing parent from \(B\) until reaching \(A\).

  • Since the output value can be negative, use a signed integer type (long long).

  • To avoid overflow from multiplication of \(S\) values and coordinate values, perform calculations using long long type (\(S\) can be up to approximately \(5000 \times 10^5 = 5 \times 10^8\), and its product with the number of nodes can reach approximately \(2.5 \times 10^{12}\)).

    Source Code

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    int N, Q;
    cin >> N >> Q;
    
    vector<long long> X(N+1), Y(N+1);
    for (int i = 1; i <= N; i++) {
        cin >> X[i] >> Y[i];
    }
    
    vector<vector<int>> adj(N+1);
    for (int j = 0; j < N-1; j++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    
    vector<bool> inverted(N+1, false);
    long long S = 0;
    
    vector<int> parent(N+1);
    
    for (int q = 0; q < Q; q++) {
        int type;
        cin >> type;
        if (type == 1) {
            int C;
            cin >> C;
            inverted[C] = !inverted[C];
        } else if (type == 2) {
            long long W;
            cin >> W;
            S += W;
        } else {
            int A, B;
            cin >> A >> B;
            
            if (A == B) {
                cout << S << "\n";
                continue;
            }
            
            // BFS from A to find path to B
            fill(parent.begin(), parent.end(), -1);
            parent[A] = A;
            queue<int> bfs;
            bfs.push(A);
            while (!bfs.empty()) {
                int u = bfs.front();
                bfs.pop();
                if (u == B) break;
                for (int v : adj[u]) {
                    if (parent[v] == -1) {
                        parent[v] = u;
                        bfs.push(v);
                    }
                }
            }
            
            // Trace path from B to A
            vector<int> path;
            int cur = B;
            while (cur != A) {
                path.push_back(cur);
                cur = parent[cur];
            }
            path.push_back(A);
            
            // Compute answer
            long long cost = 0;
            int num_nodes = (int)path.size();
            
            for (int i = 0; i + 1 < num_nodes; i++) {
                int u = path[i], v = path[i+1];
                long long xu = inverted[u] ? -X[u] : X[u];
                long long yu = inverted[u] ? -Y[u] : Y[u];
                long long xv = inverted[v] ? -X[v] : X[v];
                long long yv = inverted[v] ? -Y[v] : Y[v];
                cost += abs(xu - xv) + abs(yu - yv);
            }
            
            cost += S * (long long)num_nodes;
            
            cout << cost << "\n";
        }
    }
    
    return 0;
}

This editorial was generated by claude4.6opus-thinking.

投稿日時:
最終更新: