2019 Multi-University Training Contest 4 - AND Minimum Spanning Tree

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

  • AND Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)
    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 921
    Accepted Submission(s): 471

Problem Description

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.

Input

The 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).

Output

For 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

Hint

In the 1st test case, w(1, 2) = w(2, 1) = 0, w(1, 3) = w(3, 1) = 1, w(2, 3) = w(3, 2) = 2. There is only one minimum spanning tree in this graph, i.e. {(1, 2), (1, 3)}.
For the 2nd test case, there is also unique minimum spanning tree.

题意:给你一个N,序列中N个数字依次为1,2,3…N;
任意两点(a,b)之间的权重是 a & b ;;求最小生成树 .

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define mem(a,num) memset(a,num,sizeof(a))
const int maxn = 200000 + 10;
const int INF = 0x3f3f3f3f;
int value;
int ans[maxn],n;

int main(){
	ios::sync_with_stdio(false); cin.tie(0);      //ios::sync_with_stdio(false);cin.tie(0);
	int T;
	for(cin >> T;T !=0;T--){
		cin >> n;
		int i,j,k;
		value = 0;
		for(i = 2;i <= n;i++){
			if(i % 2 == 0){          //偶数直接跟1相连,权值+0 
				ans[i] = 1;
				value += 0;
			}else{                //奇数分2种情况 
				j = i;
				int cnt = 0;
				while(j != 0){    //奇数 / 2   (k次)后等于偶数;连接pow(2,k),权值+0; 
					if(j % 2 == 0){				//奇数一直 /2 到0为止的连接后面一位(不存在则连接1,权值+1),权值加0
						ans[i] = pow(2,cnt);
						break;
					}
					j >>= 1;
					cnt++;
				}
				if(j == 0 && i != n){
					ans[i] = i+1;
					value += 0;
				}else if(j == 0 && i == n){
					ans[i] = 1;
					value += 1;
				}
			}
		}
		cout << value << endl;
		for(int i = 2;i <= n;i++){
			i == 2?cout << ans[i]:cout << " " << ans[i];
		} 
		cout << endl;
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值