• P4551 最长异或路径(01trie模板)


    间隙

    大致题意

    给定一棵(n)个点的带权树,求最长的异或路径。

    异或路径指的是指两个结点之间唯一路径上的所有边权的异或

    (1≤n≤100000)

    分析

    01trie模板

    (f_i)表示从根节点到(i)节点的异或路径,有显然的递推公式:(f_v = f_{fa}⊕edge.w)

    根据异或的性质,(x)(y)之间的异或路径即为(f_v⊕f_u)((a⊕a = 0),即路径上重合的一部分恰好抵消)

    于是可以将每个(f_i)的二进制串从左到右插入到一颗(trie)树中,并在查询时尽可能地往与当前位相反的指针走即可

    (code)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 100010;
    struct e{
    	int u,v,w,next;
    }edge[MAXN<<1];
    int head[MAXN<<1],cnt = 0;
    void add(int u,int v,int w){
    	++cnt;
    	edge[cnt].w = w;
    	edge[cnt].u = u;
    	edge[cnt].v = v;
    	edge[cnt].next = head[u];
    	head[u] = cnt;
    }
    int n,ans = 0;
    int child[MAXN*40][2],tot = 1;
    int a[MAXN];
    void dfs(int u,int fa){
    	for(int i=head[u];i;i=edge[i].next){
    		int v = edge[i].v;
    		if(v==fa) continue;
    		a[v] = a[u]^edge[i].w;
    		dfs(v,u);
    	}
    }
    void insert(int a){
    	int p = 1;
    	for(int i=30;i>=0;i--){
    		int now = a>>i&1;
    		if(!child[p][now]) child[p][now] = ++tot;
    		p = child[p][now];
    	}
    }
    void findmax(int a){
    	int res = 0;
    	int p = 1;
    	for(int i=30;i>=0;i--){
    		int now = a>>i&1;
    		if(child[p][now^1]){
    			res|=1<<i;
    			p = child[p][now^1];
    		}
    		else{
    			p = child[p][now];
    		}
    	}
    	ans = max(ans,res);
    }
    int main(){
    	cin>>n;
    	for(int i=1;i<=n-1;i++){
    		int u,v,w;
    		cin>>u>>v>>w;
    		add(u,v,w);
    		add(v,u,w);
    	}
    	dfs(1,0);
    	for(int i=1;i<=n;i++){
    		insert(a[i]);
    		findmax(a[i]);
    	}
    	cout<<ans;
    }
    
  • 相关阅读:
    HDU6060 RXD and dividing
    Knapsack in a Globalized World --多重完全背包
    hdu 6058 Kanade's sum
    矩形面积 HDU
    Bridge Across Islands POJ
    Manors HDU
    Harry Potter and J.K.Rowling HDU
    Polygons HDU
    Jungle Outpost HDU
    CRB and Farm HDU
  • 原文地址:https://www.cnblogs.com/xcxc82/p/13907076.html
Copyright © 2020-2023  润新知