【Nowcoder】2019牛客暑期多校训练营(第五场)F maximum clique 1 | 二分图 、 最大独立集

题目大意:

给出一个序列,数字各不相同,要求选出一个最大的集合,使得这集合中任意两个数的二进制表示中都有两位及以上的不同

题目思路:

很显然是一个最大团问题

最大团 = 补图的最大独立集

也就是说,对于这个序列,用补图建边:如果两个数相差只有1位就连边

此时就表示为:假设 x , y x,y x,y连边,那么 x x x y y y就不能同时出现在一个集合里

也就是转换为了求该图的最大独立集,当然最大独立集前提是一个二分图。

那么数字各不同,又只有一位不同,那么 n 2 n^2 n2建图后,显然是一个二分图

首先给二分图染色,白色连接源点,黑色边连接汇点,然后跑一遍最大匹配即可,当然此部分可以省略,观察得到,因为只有一位不同,所以当两个数的二进制表示,1的个数奇偶性相同时,是不可能连边的,所以按照 1 1 1个数的奇偶性直接分成 2 2 2类即可

最后 n − m a x n-max nmax就是答案, m a x max max指最大匹配
最大独立集 = n - 最小点覆盖
最小点覆盖 = 最大匹配

关于路径还原:

这里很奇妙,首先要找出最小点覆盖,除去最小点覆盖的点,也就是最大独立集了:最小点覆盖,覆盖了所有边,那么这些点撤去之后,所有边都会缺失一个或者两个端点,从而构成独立集

考虑怎么还原出最小点覆盖:

对于 d i n i c dinic dinic算法的最后一次 b f s bfs bfs,是对残留网络的一次增广,如果说存在一条增广路,那么要拆散这条增广路一定会选右边的集合,因为这样点数少 1 1 1,之后再把左边已经选择了最大匹配的点集算入,就可以组成了一个最小点覆盖,从n个点中把这些点去除,变成了最大独立集

Code:

/*** keep hungry and calm CoolGuang!  ***/
/*#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)*/
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn = 5e5+700;
const int mod= 998244353;
const int up = 1e9;
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int num[maxn],b[maxn];
///网络流
struct Dinic{
    
    
    ll cnt = 2;
    struct Edge{
    
    
        int e,next;
        ll w;
    };
    int _S,_T,N;
    int head[maxn],d[maxn],cur[maxn];
    Edge edge[maxn];
    void _inint(int s,int t,int n){
    
    ///n包括S与T
        memset(head,0,sizeof(head));
        cnt = 2;
        _S = s,_T = t,N = n;
    }
    void addedge(int u,int v,ll w){
    
    
        edge[cnt] = Edge{
    
    v,head[u],w};
        head[u] = cnt++;
    }
    void Add(int u,int v,ll w){
    
    
        addedge(u,v,w);addedge(v,u,0);
        ///输出建图 用于debug 一般情况注释
        //printf("%c %lld=[%d %d]%c\n",u==_S?'S':' ',w,u,v,v==_T?'T':' ');
    }
    bool bfs(){
    
    
        for(int k=0;k<=N;k++) d[k] = 0;
        queue<int>q;q.push(_S);d[_S] = 1;
        while(!q.empty()){
    
    
            int u = q.front();q.pop();
            for(int i=head[u];i;i=edge[i].next){
    
    
                int e = edge[i].e;
                if(edge[i].w <= 0||d[e]) continue;
                d[e] = d[u]+1;
                q.push(e);
            }
        }
        for(int k=0;k<=N;k++) cur[k] = head[k];
        return (d[_T] != 0);
    }
    ll dfs(int u,ll flow){
    
    
        if(u == _T)return flow;///找到可行流
        for(int &i=cur[u];i;i=edge[i].next){
    
    
            int e = edge[i].e;
            if(d[e]!=d[u]+1||edge[i].w<=0) continue;
            ll temp = dfs(e,min(flow,edge[i].w));
            if(temp<=0) continue;
            edge[i].w -= temp;
            edge[i^1].w += temp;
            return temp;
        }
        return 0;
    }
    ll MaxFlow(){
    
    
        ll maxflow = 0,delta = 0;
        while(bfs()){
    
    
            while(delta = dfs(_S,INF)) maxflow+= delta;
        }return maxflow;
    }
    void AC(){
    
    
        for(int i=1;i<=n;i++)
            if((d[i] == 0)^b[i]) printf("%d ",num[i]);
        return;
    }
}g;
int main(){
    
    
    read(n);
    g._inint(0,n+1,n+1);
    for(int i=1;i<=n;i++){
    
    
        read(num[i]);
        b[i] = __builtin_parity(num[i]);
        if(b[i]) g.Add(0,i,1);
        else g.Add(i,n+1,1);
    }
    for(int i=1;i<=n;i++){
    
    
        for(int k=i+1;k<=n;k++){
    
    
            int temp = num[i]^num[k];
            if(!(temp&(temp-1))){
    
    
                if(b[i]) g.Add(i,k,1);
                else g.Add(k,i,1);
            }
        }
    }
    printf("%lld\n",n-g.MaxFlow());
    g.AC();
    return 0;
}

/***
5 7
1 2 3 4 5
1 2
2 3
3 4
4 5

3 1
3 2
2 1 5
1 2
2 1 3
3 1
3 5
****/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/111744002