牛客编程巅峰赛S2第10场

  • 题意:给你节点数为(n)的树,每个节点都有自己的权值,求所有路径的上的点的权值按位与的和.
  • 题解:题目给的数据很大,我们不能直接去找.因此我们可以枚举二进制([1,20])的每一位,然后再枚举所有点,看它二进制对应位置是否满足条件,之后再去dfs找(1)的连通块即可.
  • 代码:
const int N=1e6+10;
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int整型 点的个数
     * @param u int整型vector 每条边的起点
     * @param v int整型vector 每条边的终点
     * @param p int整型vector 每个点的价值
     * @return long长整型
     */

	vector<int> e[N];
	bool st[N];
	long long res=0;
	int cnt[N];

	void dfs(int u,int fa){
		res++;
		st[u]=true;
		for(auto w:e[u]){
			if(st[w] || w==fa || !cnt[w]) continue;
			dfs(w,u);
		}
	}

    long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& p) {
        // write code here
		for(int i=0;i<n-1;++i){
			e[u[i]].push_back(v[i]);
			e[v[i]].push_back(u[i]);
		}
        long long ans=0;
		for(int i=0;i<=20;++i){
			for(int j=0;j<n;++j) ((1<<i)&p[j])?cnt[j]=1:cnt[j]=0;
			memset(st,false,sizeof(st));
			for(int j=0;j<n;++j){
				if(st[j] || cnt[j]==0) continue;
				res=0;
				dfs(j,-1);
				ans+=(res+res*(res-1)/2)*(1<<i);
			}
		}
	
		return ans;
    }
};


原文地址:https://www.cnblogs.com/lr599909928/p/14158837.html