2009 Niuke Summer Multi-School Training Camp (F ifth)

Keywords: REST

Topic Links
Title: Give you a set of data, let you choose as many numbers as possible, and choose the number between the two binary representation of different digits to be greater than 1.
Thought: Reverse thinking, if there is only one difference between the two numbers, then we will build an edge between the two numbers. So that is the problem of finding a maximum independent set.
theorem

Let G be a bipartite graph with n nodes, and the size of the largest independent set of G is equal to n minus the maximum matching number.

But this problem requires not only the size, but also the output of the selected number.
So we can first find the minimum point coverage of this bipartite graph, and then the rest is the points of the largest independent set.
Finding the Minimum Point Covering of Bipartite Graphs

1. Finding the Maximum Matching of Bipartite Graphs
2 Starting from each mismatched point on the left, the process of DFS searching for augmented paths is executed again (which is bound to fail), and the visited nodes are marked.
3. Take the unmarked points on the left and the marked points on the right, and we get the minimum point coverage of the bipartite graph.

For this problem, we require the largest independent set, so the opposite is to go to the left marked point and the right unmarked point.

Here, when we construct a bipartite graph, we can divide left and right nodes according to the parity of the number of 1 under the binary of each number.

#include<bits/stdc++.h>
using namespace std;
const int N = 5010,M = N*N;
int n;
int a[N];
int head[N], to[M], nextt[M], cnt = 2;
int vis[N], match[N],sign[N];
int L[N], R[N], tot1, tot2;
void add(int u, int v) {
	to[cnt] = v, nextt[cnt] = head[u], head[u] = cnt++;
}
bool solve(int x, int y) {
	bitset<32>a(x), b(y);
	int ans = 0;
	for (int i = 0; i < 32; i++)if (a[i] != b[i])ans++;
	return ans == 1;
}

bool dfs(int x) {
	vis[x] = 1;
	for (int i = head[x], y; i; i = nextt[i]) {
		if (!vis[y = to[i]]) {
			vis[y] = 1;
			if (!match[y] || dfs(match[y])) {
				match[y] = x; match[x] = y; return true;
			}
		}
	}
	return false;
}

int main() {
	scanf("%d",&n);
	for (int i = 1; i <= n; i++)scanf("%d",a+i);
	for (int i = 1; i <= n; i++) {
		bitset<32>b(a[i]);
		if (b.count() % 2)L[++tot1] = i;
		else R[++tot2] = i;
	}

	for (int i = 1; i <= tot1; i++) {
		for (int j = 1; j <= tot2; j++) {
			if (solve(a[L[i]], a[R[j]]))add(L[i], R[j]);
		}
	}

	int ans = 0;
	for (int i = 1; i <= tot1; i++) {
		memset(vis,0,sizeof(vis));
		if (dfs(L[i]))ans++;
	}
	
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= tot1; i++) {
		if (match[L[i]])continue;
		dfs(L[i]);
	}

	printf("%d\n",n-ans);
	for (int i = 1; i <= tot1; i++) {
		if (vis[L[i]])printf("%d ",a[L[i]]);
	}
	for (int i = 1; i <= tot2; i++) {
		if (vis[R[i]]==0)printf("%d ", a[R[i]]);
	}
	return 0;
}

Posted by gerrydewar on Tue, 08 Oct 2019 11:04:41 -0700