POJ 3764:01字典树

来源:互联网 发布:asp新闻发布系统源码 编辑:程序博客网 时间:2024/04/30 04:49

题意:给出一棵树,每条边有一个权,求出树上一个路径,使得这个路径上所有边的抑或和最大。

题解:以1为根,把每个点到根的抑或和算出来,全插到01字典树,然后再拿着每个点的值去查就行了。复杂度n*32*2。别忘了把根=0插进去。


注意:POJ不给开O2,自己代码里开也没用,STL(vector)会被卡

Code:

#include<stdio.h>#include<cstring>#include<algorithm>using namespace std;const int MAX = 1e5+100;int nxt[MAX*32][2];int first[MAX*2];int des[MAX*2];int n[MAX*2];int len[MAX*2];int tot,ans,cnt,N;int bas[40];void init(){bas[0] =1;for (int i=1;i<=30;i++){bas[i] = bas[i-1]<<1;}}void clear(){ans = tot= cnt =0;memset(nxt[0],0,sizeof nxt[0]);memset(first,0,sizeof first);}void add(int x,int y,int z){tot++;des[tot] = y;len[tot] = z;n[tot] = first[x];first[x] = tot;}void input(){for (int i=1;i<N;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);u++;v++;add(u,v,w);add(v,u,w);}}int create(){cnt++;memset(nxt[cnt],0,sizeof nxt[cnt]);return cnt;}void insert(int x){int nod = 0;for (int i=30;i>=0;i--){int t = x&bas[i];t >>=i;if (!nxt[nod][t]){nxt[nod][t] = create();}nod = nxt[nod][t];}}void query(int val){int nod =0;int res =0;for (int i=30;i>=0;i--){int t = val&bas[i];t>>=i;if (nxt[nod][!t]){res+=bas[i];nod = nxt[nod][!t];}else{nod = nxt[nod][t];}}ans = max(ans,res);}void dfs(int node,int father,int val){if (node!=1){query(val);}insert(val);for (int t = first[node];t;t = n[t]){if (des[t]==father){continue;}dfs(des[t],node,val^len[t]);}}void solve(){dfs(1,0,0);printf("%d\n",ans);}int main(){init();while (scanf("%d",&N)!=EOF){clear();input();solve();}return 0;}