• 【Luogu P4551】最长异或路径


    链接:

    洛谷

    题目大意:

    给定一棵 (n) 个点的带权树,结点下标从 (1) 开始到 (n)。寻找树中找两个结点,求最长的异或路径。

    正文:

    01Trie 板子题。将每个点到根节点的异或和预处理出来,从高位到低位丢到 01Trie 里,查询时反着搜索,因为要使得异或值最大,当前位要尽量取反。

    代码:

    const int N = 1000010;
    
    int n, head[N];
    int tot;
    struct edge
    {
    	int to, val, nxt;
    }e[N << 1];
    
    void add(int u, int v, int w) {e[++tot] = (edge){v, w, head[u]}, head[u] = tot;} 
    
    struct Trie
    {
    	int ch[N][2];
    	int siz[N], tot;
    	void Ins(ll val)
    	{
    		int u = 0;
    		for (int i = 31; ~i; --i)
    		{
    			int k = (val >> i) & 1; siz[u] ++;
    			if (!ch[u][k]) ch[u][k] = ++ tot;
    			u = ch[u][k];
    		}
    	}
    	ll Query(int n, ll val)
    	{
    		int u = 0; ll ans = 0;
    		for (int i = 31; ~i; --i)
    		{
    			int k = (val >> i) & 1;
    			if (!ch[u][k ^ 1]) u = ch[u][k];
    			else if (n <= siz[ch[u][k ^ 1]]) u = ch[u][k ^ 1], ans |= 1 << i;
    			else n -= siz[ch[u][k ^ 1]], u = ch[u][k];
    		}
    		return ans;
    	}
    }t;
    
    ll sum[N], ans;
    
    void dfs (int u, int fa)
    {
    	for (int v, i = head[u]; i; i = e[i].nxt)
    	{
    		if ((v = e[i].to) == fa) continue;
    		sum[v] = e[i].val ^ sum[u];
    		dfs (v, u);
    	}
    }
    
    int main()
    {
    	scanf ("%d", &n);
    	for (int i = 1, u, v, w; i < n; i++)
    	{
    		scanf ("%d%d%d", &u, &v, &w);
    		add(u, v, w);add(v, u, w);
    	}
    	dfs(1, -1);
    	for (int i = 1; i <= n; i++)
    		t.Ins(sum[i]);
    	for (int i = 2; i <= n; i++)
    		ans = max(ans, t.Query(0, sum[i]));
    	printf ("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    MVC模式简介
    UEditor插入表格没有边框但有间距
    MVC准备前基础知识
    如何关闭ie9烦人的提示信息?
    javaScript中利用ActiveXObject来创建FileSystemObject操作文件
    win7下IIS安装与配置运行网站
    javascript函数
    减小SSN影响
    EMC (电磁兼容性)
    电源完整性设计
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14489637.html
Copyright © 2020-2023  润新知