深圳市做网站设计,wordpress欢迎页插件,wordpress keywords description,网站站点结构图想了一下#xff0c;觉得还是发单篇的题解比较合理
怎么感觉这题之前做过
先抛开建边方式不管 这一步其实挺重要的#xff0c;但是可能大多数人独立做这道题的时候都在想用位运算的性质#xff0c;而没有想到分开考虑吧#xff1f;#xff0c;考虑新建000号节点#xf…想了一下觉得还是发单篇的题解比较合理
怎么感觉这题之前做过
先抛开建边方式不管 这一步其实挺重要的但是可能大多数人独立做这道题的时候都在想用位运算的性质而没有想到分开考虑吧考虑新建000号节点问题转化为如果aiand aj0a_i\ \text{and}\ a_j0ai and aj0那么存在i→ji\to ji→j的长度为aja_jaj的边以及j→ij\to ij→i的长度为aia_iai的边求以000为根节点的最大树形图。
观察发现边权和等于将每条边看成aiaja_ia_jaiaj求和后再减去∑ai\sum a_i∑ai因此无向图的生成树也对应一个树形图。
因此可以直接跑kruskal\text{kruskal}kruskal算法。从大到小枚举边权然后枚举子集注意一下细节应该可以通过。复杂度O(318)O(3^{18})O(318)。时限开3s还是比较稳的
#includebits/stdc.h
#define ll long long
using namespace std;
int cnt[118],vs[118];
int n,m,fa[118],a[118];
ll res;
int find(int x){return fa[x]x?x:fa[x]find(fa[x]);
}
void unionset(int x,int y){int ufind(x),vfind(y);if(u!v){m-cnt[u]cnt[v]-1;res(ll)(cnt[u]cnt[v]-1)*(x|y);fa[u]v,cnt[v]1;}
}
int main(){cinn;cnt[0];for(int i0;i118;i)fa[i]i,vs[i]0;for(int i1;in;i){cina[i],cnt[a[i]];}for(int i(118)-1;i0;i--){for(int ji;j;j(j-1)i){if(cnt[j]cnt[i-j]){unionset(j,i-j);}}}for(int i1;in;i)res-a[i];coutres;
}