[2019杭电多校第四场][hdu6614]AND Minimum Spanning Tree(贪心)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6614

题目大意是有一张n个点的完全图,n个点点权为1-n,边权为两点点权按位与(&)。求最小生成树的边权和以及每个点的父节点。

由于边权为点权相与,则每个点如果可以找到他二进制位下0的最小位所代表的十进制数则两点边权为0。

例如1001(9)的最小位0(即右数第二位)所代表的十进制数0010(2),则9与2相连。

特殊情况为1111(15)的最小位0(即右数第5位)所代表的的十进制数为10000(16),要判断此处16是否存在,如果不存在则选择0001(1)与之相连,边权为1。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<vector>
 7 #define lson l, mid, i<<1
 8 #define rson  mid + 1, r, i<<1|1
 9 using namespace std;
10 typedef long long ll;
11 const int maxn = 2e5 + 10;
12 int fa[maxn];
13 int lowbit(int x) { return x & (-x); }
14 int qpow(ll a, ll b) {
15     ll ans = 0;
16     while (b) {
17         if (b & 1)
18             ans = ans * a;
19         a = a * a;
20         b /= 2;
21     }
22     return ans;
23 }
24 int main() {
25     int t;
26     scanf("%d", &t);
27     while (t--) {
28         int n;
29         scanf("%d", &n);
30         int Max = qpow(2, 60) - 1, ans = 0;
31         for (int i = 2; i <= n; i++) {
32             if (i % 2) {
33                 if (lowbit(i) == i) continue;
34                 int fat = lowbit((~i) &Max);
35                 if (fat > n)fa[i] = 1, ans++;
36                 else fa[i] = fat;
37             }
38             else
39                 fa[i] = 1;
40         }
41         printf("%d\n", ans);
42         for (int i = 2; i <= n; i++)
43             printf("%d%c", fa[i], i == n ? '\n' : ' ');
44     }
45 }

 

posted @ 2019-08-13 21:34  祈梦生  阅读(148)  评论(0编辑  收藏  举报