博客园 首页 私信博主 显示目录 隐藏目录 管理

AND Minimum Spanning Tree(二进制)HDU - 6614

 

You are given a complete graph with N vertices, numbered from 1 to N.

The weight of the edge between vertex x and vertex y (1<=x, y<=N, x!=y) is simply the bitwise AND of x and y. Now you are to find minimum spanning tree of this graph.

InputThe first line of the input contains an integer T (1<= T <=10), the number of test cases. Then T test cases follow. Each test case consists of one line containing an integer N (2<=N<=200000).OutputFor each test case, you must output exactly 2 lines. You must print the weight of the minimum spanning tree in the 1st line. In the 2nd line, you must print N-1 space-separated integers f2, f3, … , fN, implying there is an edge between i and fi in your tree(2<=i<=N). If there are multiple solutions you must output the lexicographically smallest one. A tree T1 is lexicographically smaller than tree T2, if and only if the sequence f obtained by T1 is lexicographically smaller than the sequence obtained by T2.

Sample Input

2
3
2

Sample Output

1
1 1
0
1

题意:

有N个结点,两结点之间边的权值为两个点取与,比如说结点2和结点3之间的权值 W(2,3) = 10&11 = 10,问整个图的最小生成树

第一行输出最小生成树的权值和

第二行分别输出2到N节点连接的点(如果一个节点连接了2个点的话,需要输出小的那个)

分析:看到这道题目的时候当时一脸懵逼,最小生成树的权值之和好求,但是输出相连接结点的话。。。还是规律。。

二进制的10011最优的连接结点无疑是00100(二进制),,本质就是找到第一个非1的位置,其他位置都为0就OK.

但是看一个特例:111的最有连接结点是1000,但是如果N最大为7(十进制),那就没有8(二进制1000)来进行配对了,因此111只能被迫与1进行配对。

总结下来:第一行最小生成树的权值之和只能是1或者0,然后特例只要判断n+1是否为2的幂指数就可以。

AC代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn = 2e5+10;
 7 #define LL long long
 8 #define INF 0x3f3f3f3f
 9 int T;
10 int a[maxn];
11 bool judge(int x){
12     int k=x&(x-1);
13     if(!k)return true;
14     return false;
15 }
16 int ft(int x){
17     int ans=1;
18     while(1){
19         int k=x&1;
20         x>>=1;
21         if(!k) break;
22         ans<<=1;
23     }
24     return ans;
25 }
26 
27 int main(){
28     scanf("%d",&T);
29     while(T--){
30         int n;
31         scanf("%d",&n);
32         memset(a,0,sizeof(a));
33         if(judge(n+1)) printf("1\n");
34         else printf("0\n");
35         for(int i=2;i<=n;i++){
36             int k=ft(i);
37             if(k>n) printf("1");
38             else printf("%d",k);
39             if(i==n) printf("\n");
40             else printf(" ");
41         }
42     }
43 
44     return 0;
45 }

 

posted @ 2019-08-15 19:18  Brave_WTZ  阅读(163)  评论(0编辑  收藏  举报