题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6614
题目大意是有一张n个点的完全图,n个点点权为1-n,边权为两点点权按位与(&)。求最小生成树的边权和以及每个点的父节点。
由于边权为点权相与,则每个点如果可以找到他二进制位下0的最小位所代表的十进制数则两点边权为0。
例如1010(10)的最小位0(即右数第二位)所代表的十进制数0010(2),则10与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 }