二学期2019年の個人-A週間トーナメントのタイトルの下で

質問の意味:

シーク、タイトルに示すように、(S(U_1、V_1)\)\ \(\ Oplus \)\(S(U_2、V_2)\)最大。

分析:

\(1 \)暴力ソリューション:ので\(S(U、V) \) の各点の祖先に関連する、と考えるのはとても難しい\(O(N ^ 2) \) すべてを計算する方法\(Sを(U、V)\)その祖先の値は、各頂点に対する暴力を算出することができるトラバース。カウントする\(S(U_1、V_1)\)\(\ Oplus \)\(S \(U_2、V_2)) 最大であることができる激しい\(O(P ^ {2 })\) を算出し、前記\(P \)を除去すべての重複を表す\(S(U、V) \) 数。その後、合計複雑です\(O(P ^ 2) \) この質問を渡すことはできません。\(Pの\)の最大値は超えていない\(2万* 15 \)を

\(2 \) I溶液:各頂点の重みが小で見つけることができ、単にアレイを使用\を(VIS [N] [16 ] \) 標識された\(U \)する祖先の\(U \)の排他的論理和ノードの場合\(DFS \)横断\(U \)息子\を(V \) 再計算フラグ\(V \)の排他的論理和の値。このようにする(Oを(N×16)\ \) すべて取得するために、\(S(U、V) \) 値。次に\(01 \)最大総複雑クエリにトライ側挿入端\の(O(P- * log_2(P-))\)

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

#define pb push_back

const int N = 2e4 + 5, M = N * 16 + 5;

int n, u, v, ans, w[N];
bool val[N][17], flag[M];
int tot, ch[M * 19][2];
int head[N], cnt;

struct Graph {
    int v, next;
} edge[N << 1];

void addedge(int u, int v) {
    edge[++cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

void insert(int p) {
    int u = 0, x;
    for (int i = 19; ~i; i--) {
        x = (p >> i) & 1;
        if (!ch[u][x]) ch[u][x] = ++tot;
        u = ch[u][x];
    }
}

int query(int p) {
    int u = 0, x, ans = 0;
    for (int i = 19; ~i; i--) {
        x = (p >> i) & 1;
        if (ch[u][!x]) u = ch[u][!x], ans |= (1 << i);
        else u = ch[u][x];
    }
    return ans;
}

void dfs(int u, int f) {
    val[u][w[u]] = true;
    if (!flag[w[u] * u]) {
        flag[w[u] * u] = true;
        insert(w[u] * u);
        ans = max(ans, query(w[u] * u));
    }
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        if (v == f) continue;
        for (int j = 0; j <= 15; j++) {
            if (val[u][j]) {
                val[v][j ^ w[v]] = true;
                if (!flag[(j ^ w[v]) * v]) {
                    flag[(j ^ w[v]) * v] = true;
                    insert((j ^ w[v]) * v);
                    ans = max(ans, query((j ^ w[v]) * v));
                }
            }
        }
        dfs(v, u);
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n - 1; i++) {
        scanf("%d %d", &u, &v);
        addedge(u, v), addedge(v, u);
    }
    for (int i = 1; i <= n; i++) scanf("%d", w + i);
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/ChaseNo1/p/11745224.html