제출 #1323902

#제출 시각아이디문제언어결과실행 시간메모리
1323902raqin_shahrierDrivers (BOI24_drivers)C++20
0 / 100
557 ms1114112 KiB
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 100005;
const int MAXM = 200005;

// Static Adjacency List
int head[MAXN], to[MAXM], nxt[MAXM], wt[MAXM], edge_cnt;
void add_edge(int u, int v, int w) {
    to[++edge_cnt] = v; wt[edge_cnt] = w; nxt[edge_cnt] = head[u]; head[u] = edge_cnt;
}

// HLD Arrays
int parent[MAXN], depth[MAXN], heavy[MAXN], head_path[MAXN], pos[MAXN], sz[MAXN], weight_to_parent[MAXN], root_id[MAXN], cur_pos;
int tree[MAXN * 4]; // Segment Tree

// First DFS: Calculate size, heavy child, and depth
void dfs_sz(int u, int p, int d, int r) {
    sz[u] = 1; parent[u] = p; depth[u] = d; root_id[u] = r;
    heavy[u] = -1;
    int max_sz = 0;
    for (int i = head[u]; i; i = nxt[i]) {
        if (to[i] != p) {
            weight_to_parent[to[i]] = wt[i];
            dfs_sz(to[i], u, d + 1, r);
            sz[u] += sz[to[i]];
            if (sz[to[i]] > max_sz) {
                max_sz = sz[to[i]];
                heavy[u] = to[i];
            }
        }
    }
}

// Second DFS: Path decomposition
void dfs_hld(int u, int h) {
    head_path[u] = h;
    pos[u] = ++cur_pos;
    if (heavy[u] != -1) dfs_hld(heavy[u], h);
    for (int i = head[u]; i; i = nxt[i]) {
        if (to[i] != parent[u] && to[i] != heavy[u]) {
            dfs_hld(to[i], to[i]);
        }
    }
}

// Segment Tree: Point Update and Range Max Query
void update(int node, int start, int end, int idx, int val) {
    if (start == end) { tree[node] = val; return; }
    int mid = (start + end) / 2;
    if (idx <= mid) update(2 * node, start, mid, idx, val);
    else update(2 * node + 1, mid + 1, end, idx, val);
    tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}

int query_tree(int node, int start, int end, int l, int r) {
    if (r < start || end < l) return 0;
    if (l <= start && end <= r) return tree[node];
    int mid = (start + end) / 2;
    return max(query_tree(2 * node, start, mid, l, r), query_tree(2 * node + 1, mid + 1, end, l, r));
}

// HLD Query: Max edge on path between u and v
int query_path(int u, int v, int n) {
    if (root_id[u] != root_id[v]) return 2e9 + 7;
    int res = 0;
    while (head_path[u] != head_path[v]) {
        if (depth[head_path[u]] < depth[head_path[v]]) swap(u, v);
        res = max(res, query_tree(1, 1, n, pos[head_path[u]], pos[u]));
        u = parent[head_path[u]];
    }
    if (u == v) return res;
    if (depth[u] > depth[v]) swap(u, v);
    // pos[u]+1 because we are querying edges (stored at child nodes)
    res = max(res, query_tree(1, 1, n, pos[u] + 1, pos[v]));
    return res;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n, m, u_queries; cin >> n >> m >> u_queries;
    for (int i = 0; i < m; i++) {
        int u, v, t; cin >> u >> v >> t;
        add_edge(u, v, t); add_edge(v, u, t);
    }
    for (int i = 1; i <= n; i++) {
        if (!depth[i]) {
            dfs_sz(i, i, 1, i);
            dfs_hld(i, i);
        }
    }
    for (int i = 1; i <= n; i++) {
        if (parent[i] != i) update(1, 1, n, pos[i], weight_to_parent[i]);
    }
    while (u_queries--) {
        int a, b, p; cin >> a >> b >> p;
        if (query_path(a, b, n) <= p) cout << "TAIP\n";
        else cout << "NE\n";
    }
    return 0;
}
#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...