zoukankan      html  css  js  c++  java
  • AND Minimum Spanning Tree(二进制)HDU

    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
    ");
    34         else printf("0
    ");
    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("
    ");
    40             else printf(" ");
    41         }
    42     }
    43 
    44     return 0;
    45 }
    有些目标看似很遥远,但只要付出足够多的努力,这一切总有可能实现!
  • 相关阅读:
    Java内存模型之重排序
    JAVA虚拟机:对象的创建过程
    单链表——基本操作
    new File()
    JVM回收方法区内存
    强软弱虚---强引用、软引用、弱引用、虚引用
    线性表(二)——链式存储
    JVM中判断对象是否存活的方法
    GC算法 垃圾收集器
    线性表(一)——顺序结构
  • 原文地址:https://www.cnblogs.com/Bravewtz/p/11359976.html
Copyright © 2011-2022 走看看