链接: 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;
}
}