Trie樹_POJ3764_The xor-longest Path
阿新 • • 發佈:2018-11-09
思路分析:
根據異或運算滿足結合律和交換律, 且x XOR x = 0, x XOR 0 = x. 考慮選定題目中給定樹的一點為樹根r, 計算所有點到r的異或路徑值, 設點i到根r的異或路徑值為a, 點j到點根r的異或路徑值為b, 那麼點i到點j的異或路徑值為a XOR b. 至此, 題目轉換為計算若干個數兩兩異或的最大值問題(參見之前講解題目CH1602的博文). 具體參見如下AC程式碼:
//POJ3764_The xor-longest Path #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAX = 1e5 + 5; int po[MAX << 1], head[MAX], nex[MAX << 1], weight[MAX << 1], tot; int xorval[MAX];//點i到根的異或路徑值 int trie[MAX * 31 + 5][2], ttot; //計算點u的所有後代結點到根的路徑的異或值 bool calc[MAX]; void clacXor(int u){ for(int i = head[u]; i; i = nex[i]) if(!calc[po[i]]) xorval[po[i]] = xorval[u] ^ weight[i], calc[po[i]] = true, clacXor(po[i]); } int main(){ int n; while(~scanf("%d", &n)){ memset(calc, false, sizeof(calc)), memset(trie, 0, sizeof(trie)); memset(nex, 0, sizeof(nex)), memset(head, 0, sizeof(head)); tot = 0, ttot = 0; for(int i = 1, u, v, w; i < n; ++i){ scanf("%d %d %d", &u, &v, &w); if(!head[u]) head[u] = ++tot, po[tot] = v, weight[tot] = w; else po[++tot] = v, nex[tot] = head[u], head[u] = tot, weight[tot] = w; if(!head[v]) head[v] = ++tot, po[tot] = u, weight[tot] = w; else po[++tot] = u, nex[tot] = head[v], head[v] = tot, weight[tot] = w; } calc[0] = true, xorval[0] = 0; clacXor(0); //計算xorval[0...n - 1]兩兩異或的最大值 int ans = 0; for(int i = 0; i < n; ++i){ int tans = 0, k = 0; for(int j = 30; j >= 0; --j){ int b = xorval[i] >> j & 1; if(trie[k][!b]) k = trie[k][!b], tans |= 1 << j; else k = trie[k][b]; } ans = max(ans, tans), k = 0; for(int j = 30; j >= 0; --j){ int b = xorval[i] >> j & 1; if(!trie[k][b]) trie[k][b] = ++ttot, k = trie[k][b]; else k = trie[k][b]; } } cout << ans << endl; } return 0; }