[construction] Codeforces 1615D X(or)-mas Tree

General idea of the topic

Given a tree with \ (n(1\leq n\leq 2\times 10^5) \) points, some edges of the tree have edge weight and some edges have no edge weight. Given \ (m(1\leq m\leq 2\times 10^5) \) restrictions, whether the number of \ (1 \) bits on the exclusive or sum of edge weights on the path from \ (u \) to \ (v \) is odd or even. Now it is required to give edge weight to the edge without edge weight, so that all restrictions are met.

Problem solution

Let \ (f(x) \) represent the parity of the number of \ (1 \) on the binary bit of \ (x \), that is, if there are even \ (1 \) on the binary bit of \ (x \), then \ (f(x)=0 \); If there are an odd number of \ (1 \) on the binary bit of \ (x \), then \ (f(x)=1 \). Assuming that there are a series of edge weights \ (\ {w_1,w_2,\cdots,w_k \} \) on the path from \ (u \) to \ (v \), each time \ (f (w_1 \ bigopus w_2 \ bigopus \ cdots \ bigopus w_k) = 0 \) or \ (f (w_1 \ bigopus w_2 \ bigopus \ cdots \ bigopus w_k) = 1 \) is limited. Obviously, there is \ (f (w_1 \ bigopus w_2 \ bigopus \ cdots \ bigopus w_k) = f (w_1) \ bigopus f (w_2) \ bigopus \ cdots \ bigopus f (w_k) \), so we can regard the original edge weight \ (w \) as \ (f(w) \), and the edge weight to be given is either \ (0 \) or \ (1 \).

Let \ (s[u] \) represent the exclusive or sum of \ (f(w) \) on the path from \ (U \) to the root, then \ (s[u] \ bigopus [v] = 0 \) or \ (s[u] \ bigopus [v] = 1 \) are limited each time. For the edge \ ((u,v,w) \) with existing edge weight, it is equivalent to limiting \ (s[u] \ bigopus [v] = f(w) \). Therefore, we can create a new graph for all these restrictions. When the value of \ (s[u] \ bigopus [v] \) is limited, an edge is directly connected between \ (u,v \), and the edge weight is \ (s[u] \ bigopus [v] \). At this time, the exclusive or of the point weights \ (s[u],s[v] \) of \ (u,v \) should be equal to the edge weight. In the new graph, several connected blocks can be divided. In each connected block, only when the point weight \ (s[u] \) of a point \ (U \) is equal to \ (0 \) or \ (1 \) at the beginning, all the point weights in the connected block have been determined and can be obtained through XOR edge weight transfer. If there is a contradiction whether the point weight is assigned to \ (0 \) or \ (1 \), there is no solution. So we calculate the \ (s[u] \) of a combination method. Finally, for the edge \ ((fa,u) \) without edge weight at the beginning, if \ (FA \) is the father of \ (U \), the edge weight of \ ((fa,u) \) can be assigned as \ (s[u] \ bigopolus [fa] \).

Time complexity \ (O(n+m) \).

Code

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

template<typename elemType>
inline void Read(elemType& T) {
    elemType X = 0, w = 0; char ch = 0;
    while (!isdigit(ch)) { w |= ch == '-';ch = getchar(); }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    T = (w ? -X : X);
}

struct Graph {
    struct edge { int Next, to, w; };
    edge G[800010];
    int head[200010];
    int cnt;

    Graph() :cnt(2) {}
    void clear(int n) {
        cnt = 2;fill(head, head + n + 2, 0);
    }
    void add_edge(int u, int v, int w) {
        G[cnt].w = w;
        G[cnt].to = v;
        G[cnt].Next = head[u];
        head[u] = cnt++;
    }
};
Graph G, G2;
bool vis[200010];
int s[200010];
int T, n, m;

inline int f(int x) { return __builtin_parity(x); }

void Output(int u, int fa) {
    for (int i = G.head[u];i;i = G.G[i].Next) {
        int v = G.G[i].to;
        if (v == fa) continue;
        if (G.G[i].w == -1) printf("%d %d %d\n", u, v, s[u] ^ s[v]);
        else printf("%d %d %d\n", u, v, G.G[i].w);
        Output(v, u);
    }
}

vector<int> buf;

bool DFS(int u) {
    vis[u] = true;
    buf.push_back(u);
    for (int i = G2.head[u];i;i = G2.G[i].Next) {
        int v = G2.G[i].to, w = G2.G[i].w;
        if (vis[v]) {
            if (s[v] ^ s[u] != w) return false;
            continue;
        }
        s[v] = w ^ s[u];
        if (!DFS(v)) return false;
    }
    return true;
}

int main() {
    Read(T);
    while (T--) {
        Read(n);Read(m);
        G.clear(n);
        G2.clear(n);
        for (int i = 1;i <= n - 1;++i) {
            int u, v, w;
            Read(u); Read(v); Read(w);
            G.add_edge(u, v, w);
            G.add_edge(v, u, w);
            if (w != -1) {
                w = f(w);
                G2.add_edge(u, v, w);
                G2.add_edge(v, u, w);
            }
        }
        fill(vis + 1, vis + n + 1, false);
        bool flag = true;
        for (int i = 1;i <= m;++i) {
            int u, v, w;
            Read(u); Read(v); Read(w);
            if (u == v) {
                if (w) flag = false;
                continue;
            }
            G2.add_edge(u, v, w);
            G2.add_edge(v, u, w);
        }
        if (!flag) { printf("NO\n"); continue; }
        for (int u = 1;u <= n;++u) {
            if (vis[u]) continue;
            s[u] = 0; buf.clear();
            if (!DFS(u)) {
                for (auto x : buf) vis[x] = false;
                buf.clear(); s[u] = 1;
                if (!DFS(u)) { flag = false; break; }
            }
        }
        if (!flag) {
            printf("NO\n");
            continue;
        }
        printf("YES\n");
        Output(1, 0);
    }
    return 0;
};

Keywords: CodeForces

Added by Jurik on Tue, 04 Jan 2022 14:35:56 +0200