2019 Bullock Summer Multi-School Training Camp (Fifth Session) F maximum clique 1 [The largest independent set of bipartite graphs]

Title description

You are given a set S containing n distinct positive integers a_1,a_2,...,a_n​.

Please find a subset of S which has the maximum size while satisfying the following constraint:

The binary representations of any two numbers in this subset must have at least two different bits.

If there are multiple valid subsets, please output any one of them.

Enter description 

The input contains only two lines.

The first line contains an integer N denoting the size of S.
The second line contains N positive integers a_1,a_2,...,a_n​ denoting the members of set S.

1 \ leq N \ leq 5000

1 \ leq a_i \ leq 10 ^ 9

* all a_i​ are distinct

Output description 

You should output two lines.

The first line contains one integer m denoting the size of the subset you found.

The second line contains m positive integers denoting the member of this subset.

Example input

5
3 1 4 2 5

Sample output

3
4 1 2

Explanation

(11_2) and 1 (01_2) has only 1 different bit so they can not be in the set together. 4 (100_2) and 1 (001_2) has 2 different bits so they can be in the set together.

Following unordered pairs are allowed to be in the set together: <1, 2>, <1, 4>, <2, 4>, <2, 5>, <3, 4>, <3, 5>. Thus the maximum set is of size 3 ({1, 2, 4}).

The main idea:

Given a set, the largest subset is required, and all data in the subset must be at least two bits different in binary representation.

analysis:

According to the description of the example, it is conceivable that the connection between the two data points that meet the condition can form an undirected graph, so that the maximum clique of the graph is required. The maximum clique problem and the maximum independent set problem are complementary. Consider the maximum independent set of the complement graph. The edge of the complementary graph represents that the two numbers have one and only one difference (the number of ones in binary differs by one).

It can be proved that the complementary graph is a bipartite graph, that is, there is no singular ring: for a starting point o, assuming that it exists in an singular ring, then the number of two numbers x and y connected directly to o are either the same or different 2 (ie even number), assuming the length of the loop is 3 obviously x, y should not be connected by edges, contradicting the assumption. Induced to any odd-length loop, the difference between the last two connected numbers 1 is even, contradicting the assumption.

Then the problem turns into finding the largest independent set of bipartite graphs. You can use the Hungarian algorithm to find the maximum number of matches, the maximum independent set (number) = the number of all vertices-the maximum number of matches

It is also required to give the number in the subset, that is, to give the scheme of the largest independent set. Therefore, in the bipartite graph, for all non-matching points on the left, DFS finds an augmenting path to mark all points on the path, then the last marked point on the left and the unmarked point on the right are the answer.

See the code for specific explanation.

#include <bits/stdc++.h>

#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

const int maxn = 5005;

int head[maxn];

int ans=0; 
int n;
ll a[maxn];
int col[maxn];
int vis[maxn];
int match[maxn];

struct node{

    int u,v,w;

    int next;

}edge[maxn*maxn];

void add(int u,int v,int w){//向邻接表中加边 

    edge[ans].u=u;

    edge[ans].v=v;

    edge[ans].w=w;

    edge[ans].next=head[u];

    head[u]=ans++;

}

void cdfs(int u, int color){//给二分图染色,左侧的点为 1,右侧的点为 2 
    col[u] = color;
    for(int i=head[u];i!=-1;i=edge[i].next){
    	int t=edge[i].v;
    	if (!col[t])
            cdfs(t, 3 - color);
    }
        
}

bool dfs(int u){//匈牙利算法,尝试寻找增广路 
    vis[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].v;
        if(vis[v]) continue;
        vis[v]=1;
        if(!match[v]||dfs(match[v])){
            match[v]=u;
            match[u]=v;
            return true;
        }
    }
    return false;
}

bool ispair(ll a,ll b){//判断两点之间是否连线 
	ll tmp=a^b;
	tmp-=(tmp&-tmp);//这里对两数异或后的数据减去它的lowbit值,若剩下为0,则连线 
	if(tmp>0)  return false;
	else return true;
}

int main()

{

	scanf("%d",&n);
	rep(i,1,n){
		scanf("%lld",&a[i]);
	}
	memset(head,-1,sizeof(head));
	rep(i,1,n){
		rep(j,i+1,n){
			if(ispair(a[i],a[j])){
				add(i,j,1);
				add(j,i,1);
			}
		}
	}
	memset(col,0,sizeof(col));
	//将图划分为左右两部分 
	rep(i,1,n){
		if(col[i]==0) cdfs(i,1);
	}
	//得到最大匹配数 
	int cnt=0;
	rep(i,1,n){
		if(col[i]==1){//左侧点调用DFS 
			memset(vis,0,sizeof(vis));
			if(dfs(i))  cnt++;
		}
	}
	memset(vis,0,sizeof(vis));
	rep(i,1,n){
		if(col[i]==1){
			if(!match[i])  dfs(i);//左侧未匹配的点 
		}
	}
	printf("%d\n",n-cnt);//所有顶点数-最大匹配数
        for(int i=1;i<=n;i++){
            if(col[i]==1&&vis[i]) printf("%d ",a[i]);
            if(col[i]==2&&!vis[i]) printf("%d ",a[i]);
        }
        printf("\n"); 
	return 0;

}

 

Published 30 original articles · won 5 · 900 views

Guess you like

Origin blog.csdn.net/qq_42840665/article/details/98250688