牛客程式設計巔峰賽S2第10場 - 鑽石&王者 C.牛牛的路徑和 (位運算,dfs)
阿新 • • 發佈:2020-12-19
- 題意:給你節點數為\(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; } };