2019 cattle off more school fifth F maximum clique 1 maximum independent set

Meaning of the questions: n give you the number, now you can choose a maximum number of sets such that any binary set of two numbers indicates that at least two different, ask how much this collection is the largest? And outputs the specific programs. To ensure that the number n of mutually different.

Ideas: easy to find, if not two numbers at the same time in the collection, both the binary representation must be a different (because the number of n different from each other, so be sure there will be no two-bit binary numbers necessarily the same) . So we might as well put every number and it is only one of several different even one side, then the original problem becomes to find the most points on a graph, so that has not changed between any two directly connected, and this problem It is the largest independent set problem. Further, since the number of n different from each other, so this is not necessarily FIG ring length is an odd number, i.e., this must be a bipartite graph in FIG. So, now the question becomes, seeking a bipartite graph of maximum independent set output size and specific programs. We all know that the independent set size is n - the maximum number of matches, how specific programs seek it? We know the minimum and maximum independent set point coverage is a complementary relationship, then we can find the minimum point of the cover, not the point of the minimum point coverage is the largest independent set of points.

Constructors minimum point covered are as follows (from "algorithm contest Step-up Guide"):

1: obtaining the maximum matching of the bipartite graph.

2: the left of each non-matching point of view, and then perform a dfs looking for augmenting paths process (this process will fail), and mark the node visited along the way.

3: Take node in the left portion is not labeled, a right portion labeled nodes, the minimum point is obtained covering the bipartite graph.

For this problem, after the construction of the map, we first search by determining which points to the left, which points to the right, after performing bipartite graph maximum matching. Finally, the enumeration point, if this point is not the point and it matches (ie non-matching point), from this point further augmented. Finally, the minimum point is not covered in the points included in the answer.

Code:

#include <bits/stdc++.h>
#define pii pair<int, int>
using namespace std;
const int maxn = 5010;
int a[maxn];
bool v[maxn], l[maxn];
bool va[maxn], vb[maxn];
vector<int> rea, reb;
int match[maxn];
vector<int> G[maxn], ans;
void add(int x, int y) {
	G[x].push_back(y);
	G[y].push_back(x);
}
bool dfs(int x) {
	va[x] = 1;
	v[x] = 1;
	for (int i = 0; i < G[x].size(); i++) {
		int y = G[x][i];
		if(!vb[y]) {
			vb[y] = 1;
			if(!match[y] || dfs(match[y])) {
				match[y] = x;
				return 1;
			}
			v[y] = 1;
		}
	}
	return 0;
}
void dfs1(int x, int dep) {
	if(dep & 1) {
		rea.push_back(x);
		l[x] = 1;
 	} else {
		reb.push_back(x);
		l[x] = 0;
	}
	v[x] = 1;
	for (int i = 0; i < G[x].size(); i++) {
		int y = G[x][i];
		if(v[y]) continue;
		dfs1(y, dep + 1);
	}
}
int main() {
	int n;
	//freopen("in.txt", "r", stdin);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++)
		for (int j = i + 1; j <= n; j++) {
			if(__builtin_popcount(a[i] ^ a[j]) == 1) {
				add(i, j);
			}
		}
	for (int i = 1; i <= n; i++) {
		if(v[i]) continue;
		dfs1(i, 1);
	}
	memset(v, 0, sizeof(v));
	if(rea.size() > reb.size()) {
		swap(rea, reb);
		for (int i = 1; i <= n; i++)
			l[i] ^= 1;
	}
	for (int i = 0; i < rea.size(); i++) {
		memset(va, 0, sizeof(va));
		memset(vb, 0, sizeof(vb));
		dfs(rea[i]);
	}
	memset(va, 0, sizeof(va));
	memset(vb, 0, sizeof(vb));
	memset(v, 0, sizeof(v));
	for (int i = 0; i < rea.size(); i++) {
		bool flag = 0;
		int x = rea[i];
		for (int j = 0; j < G[x].size(); j++) {
			int y = G[x][j];
			if(match[y] == x) {
				flag = 1;
				break;
			}
		}
		if(flag == 0 && v[x] == 0) {
			dfs(x);
		}
	}
	for (int i = 1; i <= n; i++) {
		if(l[i] == 1 && v[i] == 1) ans.push_back(i);
		else if(l[i] == 0 && v[i] == 0) ans.push_back(i);
	}
	printf("%d\n", ans.size());
	for (int i = 0; i < ans.size(); i++) {
		printf("%d ", a[ans[i]]);
	}
	printf("\n");
}

 

Guess you like

Origin www.cnblogs.com/pkgunboat/p/11286208.html