牛客编程巅峰赛:牛牛的路径和(并查集)

链接:https://ac.nowcoder.com/acm/contest/10167/C
来源:牛客网

题目描述
牛牛有一棵n个节点的树,每个节点都有一个价值p[i],对于某一条路径,定义路径的价值为路径上所有点的价值在二进制下按位与的值。现在,牛牛想知道所有树上路径的价值和为多少,你可以帮帮他吗?
注意,单独的一个点也算一条路径。
示例1
输入
复制
4,[0,1,2],[1,2,3],[1,2,2,1]
返回值
复制
8
说明
共有5条路径对答案有贡献,(1->2)贡献为2,(0)贡献为1,(1)贡献为2,(2)贡献为2,(3)贡献为1,所以答案为2+1+2+2+1=8。
备注:
1≤n≤1e5,0≤p[i]≤2^20 ,0≤u[i],v[i]<n

**思路:*我们可以枚举每一位,通过每一位的连通集合大小能够快速求出枚举的当前位在这个集合中所有路径上的贡献【集合大小为n的话其路径数为n(n+1)/2】。

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int整型 点的个数
     * @param u int整型一维数组 每条边的起点
     * @param v int整型一维数组 每条边的终点
     * @param p int整型一维数组 每个点的价值
     * @return long长整型
     */
    private int[] f,size;
    public long solve (int n, int[] u, int[] v, int[] p) {
        // write code here
        long ans=0;
        f=new int[n];
        size=new int[n];
        for(int i=0;i<n;i++)
            f[i]=i;
        for(int x=0;x<20;x++){
            Arrays.fill(size,0);
            for(int i=0;i<n;i++)
                f[i]=i;
            for(int i=0;i<n-1;i++){
                if((p[u[i]]>>x&1)!=0 && (p[v[i]]>>x&1)!=0)
                    f[find(u[i])]=find(v[i]);
            }
            for(int i=0;i<n;i++)
                size[find(i)]++;
            for(int i=0;i<n;i++){
                if((p[i]>>x&1)!=0)
                    ans+=size[i]*(size[i]+1L)/2<<x;
            }
        }
        return ans;
    }
    private int find(int x){
        if(f[x]==x)
            return x;
        return f[x]=find(f[x]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值