Campamento de entrenamiento multi-escuela de verano Bullock 2019 (quinta sesión) F máxima camarilla 1 [El conjunto independiente más grande de gráficos bipartitos]

Descripción del título

Se le da un conjunto S que contiene n enteros positivos distintos a_1, a_2, ..., a_n.

Encuentre un subconjunto de S que tenga el tamaño máximo mientras satisface la siguiente restricción:

Las representaciones binarias de dos números cualquiera en este subconjunto deben tener al menos dos bits diferentes.

Si hay varios subconjuntos válidos, envíe uno de ellos.

Ingrese la descripción 

La entrada contiene solo dos líneas.

La primera línea contiene un número entero N que indica el tamaño de S.
La segunda línea contiene N números enteros positivos que a_1, a_2, ..., a_nindican los miembros del conjunto S.

1 \ leq N \ leq 5000

1 \ leq a_i \ leq 10 ^ 9

* todos aison distintos

Descripción de salida 

Deberías generar dos líneas.

La primera línea contiene un número entero m que indica el tamaño del subconjunto que encontró.

La segunda línea contiene m enteros positivos que denotan el miembro de este subconjunto.

Entrada de ejemplo

5
3 1 4 2 5

Salida de muestra

3
4 1 2

Explicación

(11_2)y 1  (01_2)tiene solo 1 bit diferente, por lo que no pueden estar juntos en el conjunto. (100_2)y 1  (001_2)tiene 2 bits diferentes para que puedan estar juntos en el conjunto.

Los siguientes pares desordenados pueden estar juntos en el conjunto: <1, 2>, <1, 4>, <2, 4>, <2, 5>, <3, 4>, <3, 5>. Por lo tanto, el conjunto máximo es de tamaño 3 ({1, 2, 4}).

La idea principal:

Dado un conjunto, se requiere el subconjunto más grande y todos los datos en el subconjunto deben tener al menos dos bits diferentes en representación binaria.

Análisis:

Según la descripción del ejemplo, es concebible que la conexión entre los dos puntos de datos que satisfacen la condición pueda formar un gráfico no dirigido, de modo que lo que se requiere es la camarilla más grande del gráfico. El problema de la camarilla máxima y el problema del conjunto independiente máximo son complementarios. Considere el conjunto independiente máximo del gráfico del complemento. El borde del gráfico complementario representa que los dos números tienen una y solo una diferencia (el número de unos en binario difiere en uno).

Se puede demostrar que el gráfico complementario es un gráfico bipartito, es decir, no hay un anillo singular: para un punto de partida o, suponiendo que exista en un anillo singular, entonces el número de dos números x e y conectados directamente a o son iguales o diferentes 2 (es decir, número par), suponiendo que la longitud del bucle es obviamente 3 x, y no debe estar conectado por bordes, lo que contradice la suposición. Inducido a cualquier bucle de longitud impar, la diferencia entre los dos últimos números conectados 1 es par, contradiciendo el supuesto.

Luego, el problema se convierte en encontrar el conjunto independiente más grande de gráficos bipartitos. Puede usar el algoritmo húngaro para encontrar el número máximo de coincidencias, el conjunto independiente máximo (número) = el número de todos los vértices, el número máximo de coincidencias

También se requiere dar el número en el subconjunto, es decir, dar el esquema del conjunto independiente más grande. Por lo tanto, en el gráfico bipartito, para todos los puntos que no coinciden a la izquierda, DFS encuentra una ruta de aumento para marcar todos los puntos en la ruta, luego el último punto marcado a la izquierda y el punto sin marcar a la derecha son la respuesta.

Vea el código para una explicación específica.

#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;

}

 

30 artículos originales publicados · ganó 5 · 900 visitas

Supongo que te gusta

Origin blog.csdn.net/qq_42840665/article/details/98250688
Recomendado
Clasificación