A | Minimum Cost Perfect Matching |
链接:https://www.nowcoder.com/acm/contest/145/A
来源:牛客网
题目描述
You have a complete bipartite graph where each part contains exactly n nodes, numbered from 0 to n - 1 inclusive.
The weight of the edge connecting two vertices with numbers x and y is (bitwise AND).
Your task is to find a minimum cost perfect matching of the graph, i.e. each vertex on the left side matches with exactly one vertex on the right side and vice versa. The cost of a matching is the sum of cost of the edges in the matching. denotes the bitwise AND operator. If you're not familiar with it, see {https://en.wikipedia.org/wiki/Bitwise_operation#AND}.
输入描述:
The input contains a single integer n (1 ≤ n ≤ 5 * 105).
输出描述:
Output n space-separated integers, where the i-th integer denotes pi (0 ≤ pi ≤ n - 1, the number of the vertex in the right part that is matched with the vertex numbered i in the left part. All pi should be distinct. Your answer is correct if and only if it is a perfect matching of the graph with minimal cost. If there are multiple solutions, you may output any of them.
示例1
输入
复制
3
输出
复制
0 2 1
说明
For n = 3, p0 = 0, p1 = 2, p2 = 1 works. You can check that the total cost of this matching is 0, which is obviously minimal.
题意:0 2 1 => pi (权值) => 右顶点
0 1 2 => i (下标) => 左顶点 (其中 pi&i 和最小,求pi)
题解:通过观察,所有情况都是0,然后求出每个下标的(按位取反)
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<bitset>
using namespace std;
typedef unsigned long ll;
ll s[500005]; // 保存 pi
ll v[500005]; // 标记 是否存在相同 pi
int L(int n){ // 得到 最大位数 的长度
int ans=0;
while(n){
n/=2;
ans++;
}
return ans;
}
int main(){
int n;
scanf("%d",&n);
int len=L(n-1);
memset(s,-1,sizeof(s));
for(int i=n-1;i>=0;i--){
if(s[i]!=-1) // 优化
continue;
bitset<20>bit(i);
bit.flip(); // 每位都取反
int ans=0;
for(int j=0;j<len;j++){
if(bit[j])
ans+=pow(2,j);
}
int sum=len-1;
while(ans>(n-1)||v[ans]){ // 判断是否不在范围内 或 已经用过
if(bit[sum]){
ans-=pow(2,sum); // 位数减少
}
sum--;
}
s[i]=ans; // a&b==0 那么 b&a==0 直接得到两个pi
s[ans]=i;
v[i]=1;
v[ans]=1;
}
for(int i=0;i<n;i++)
printf("%d ",s[i]);
return 0;
}