01 08 2020

01Trie。但是我在建树的时候没有记录父亲指针,然后两个指针光往下跳没往回跳了emmmm太坑了!浪费爷好多时间emmm
总体思想是树上(u,v)异或路径等于从根节点到u的异或路径异或上从根节点到y的异或路径。因为一个数异或两次就等于没有异或。所以也不用求lca啦!

#include<bits/stdc++.h>
#define maxn 100010
using namespace std;
struct Trie_Tree{
    Trie_Tree *so[2],*fa;
    int nu;
    Trie_Tree(){
        so[0]=so[1]=fa=NULL;
    }
    void add(int num,int pos){
        if(pos<0) {nu=num;return;}
        bool b=(1<<pos)&num;
        if(so[b]==NULL) (so[b]=new Trie_Tree)->add(num,pos-1);
                    else so[b]->add(num,pos-1);
        so[b]->fa=this;
    }    
}*Ttr;
Trie_Tree *tmp1,*tmp2;
int ans[35],anss,sum;
void query(int pos){
    bool tag=false;
    if(pos<0){
        sum=0;
        for(int i=0;i<=30;++i)
            sum+=(1<<i)*ans[i];
        anss=max(anss,sum);
        return;
    }
    if(tmp1->so[1]!=NULL&&tmp2->so[0]!=NULL){
        tag=true;
        ans[pos]=1;
        tmp1=tmp1->so[1];
        tmp2=tmp2->so[0];
        query(pos-1);
        tmp1=tmp1->fa;
        tmp2=tmp2->fa;
        ans[pos]=0;
    }
    if(tmp1->so[0]!=NULL&&tmp2->so[1]!=NULL){
        tag=true;
        ans[pos]=1;
        tmp1=tmp1->so[0];
        tmp2=tmp2->so[1];
        query(pos-1);
        tmp1=tmp1->fa;
        tmp2=tmp2->fa;
        ans[pos]=0;
    }
    if(tag) return;
    if(tmp1->so[1]!=NULL&&tmp2->so[1]!=NULL){
        tmp1=tmp1->so[1];
        tmp2=tmp2->so[1];
        query(pos-1);
        tmp1=tmp1->fa;
        tmp2=tmp2->fa;
    }
    if(tmp1->so[0]!=NULL&&tmp2->so[0]!=NULL){
        tmp1=tmp1->so[0];
        tmp2=tmp2->so[0];
        query(pos-1);
        tmp1=tmp1->fa;
        tmp2=tmp2->fa;
    }
}
struct node{
    int to,wi;
    node*next;
}*con[maxn];
void addedge(int x,int y,int w){
    node*p=new node;
    p->to=y;p->wi=w;
    p->next=con[x];
    con[x]=p;
}
bool vis[maxn];
int f[maxn];
void dfs(int v){
    vis[v]=true;
    for(node*p=con[v];p;p=p->next)
    if(!vis[p->to]){
        f[p->to]=f[v]^p->wi;
        dfs(p->to);
    }
}
int n;
int main(){
    scanf("%d",&n);
    int x,y,w;
    for(int i=1;i<n;++i){
        scanf("%d%d%d",&x,&y,&w);
        addedge(x,y,w);addedge(y,x,w);
    }
    dfs(1);
    Ttr=new Trie_Tree();
    int mx=0;
    for(int i=1;i<=n;++i)
        Ttr->add(f[i],30);
    tmp1=tmp2=Ttr;
    query(30);
    cout<<anss;
    return 0;
}
延伸阅读
  1. Burnside引理和polya定理
  2. [LuoguP3834]主席树模板题 静态区间K大
  3. [LuoguP2580]于是他错误的点名开始了
  4. [LuoguP3950] 部落冲突
  5. [HNOI2012] 永无乡
  6. [BJOI2016] 回转寿司
  7. [Codeforces 547B] Mike and Feet
  8. 午夜杂谈
更多阅读
  1. 上一篇:[LuoguP2580]于是他错误的点名开始了
  2. 下一篇:[LuoguP3834]主席树模板题 静态区间K大
发表评论 抢沙发