zoukankan      html  css  js  c++  java
  • maximum clique 1

    maximum clique 1

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    Special Judge, 64bit IO Format: %lld

    题目描述

    You are given a set S containing n distinct positive integers a1,a2,…,an.

    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.

    输入描述:

    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 a1,a2,…,aN denoting the members of set S.

    * 1≤N≤5000

    * 1≤ai≤1e9

    * all ai are distinct

    输出描述:

    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.

    输入

    5
    3 1 4 2 5

    输出

    3
    4 1 2

    说明

    3 (112) and 1 (012) has only 1 different bit so they can not be in the set together. 4 (1002) and 1 (0012) 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}).

    题意:在一个集合中求一个最大的子集,使得子集里任意两个数之间至少有两个二进制位不同。
    思路:两个相异的数至少两个bit不一样的否命题是:恰一个bit不一样。然后考虑到A和B一个bit不一样,A和C一个bit不一样,A,B,C各不相同,那么B和C一定不会只有一个bit不一样,所以若是两个数只有一个bit不一样,我们就在它们之间连一条边,可以发现这个图是个二分图。答案就是这个二分图的最大点独立集。
    #include<bits/stdc++.h>
    #define N 5050
    using namespace std;
    
    typedef struct
    {
        int to,next;
        long long flow;
        bool is_match;
    }ss;
    
    ss edg[64*N];
    int now_edge=0,s,t;
    int head[N];
    
    void addedge(int u,int v)
    {
        edg[now_edge]=(ss){v,head[u],0};
        head[u]=now_edge++;
    }
    
    void addedge(int u,int v,long long flow)
    {
       // printf("%d %d
    ",u,v);
    
        edg[now_edge]=(ss){v,head[u],flow};
        head[u]=now_edge++;
    
        edg[now_edge]=(ss){u,head[v],0};
        head[v]=now_edge++;
    }
    
    int dis[N];
    
    bool bfs()
    {
        memset(dis,0,sizeof(dis));
        queue<int>q;
        q.push(s);
        dis[s]=1;
    
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            for(int i=head[now];i!=-1;i=edg[i].next)
            {
                ss &e=edg[i];
                if(e.flow>0&&dis[e.to]==0)
                {
                    dis[e.to]=dis[now]+1;
                    q.push(e.to);
                }
            }
        }
    
        if(dis[t]==0)return 0;
        return 1;
    }
    
    int current[N];
    long long dfs(int x,long long maxflow)
    {
        if(x==t)return maxflow;
        for(int i=current[x];i!=-1;i=edg[i].next)
        {
            current[x]=i;
            ss &e=edg[i];
            if(e.flow>0&&dis[e.to]==dis[x]+1)
            {
                long long flow=dfs(e.to,min(maxflow,e.flow));
                if(flow!=0)
                {
                    e.flow-=flow;
                    edg[i^1].flow+=flow;
                    return flow;
                }
            }
        }
        return 0;
    }
    
    long long dinic()//最大流
    {
        long long ans=0,flow;
        while(bfs())
        {
            for(int i=0;i<N;i++)current[i]=head[i];
            while(flow=dfs(s,LLONG_MAX/2))ans+=flow;
        }
        return ans;
    }
    
    void init()
    {
        for(int i=0;i<N;i++)head[i]=-1;
        now_edge=0;
    }
    
    int arr[N];
    int color[N]={0};
    
    void Bipartite_graph_coloring(int x,int now_color)//二分图染色
    {
        if(color[x])return;
        color[x]=now_color;
        for(int i=head[x];i!=-1;i=edg[i].next)Bipartite_graph_coloring(edg[i].to,now_color*-1);
    }
    
    bool is_match_vertex[N]={0};
    int is_ans[N]={0};
    void dfs(int x,int type)//寻找最小点覆盖集中的点,不在该集合中的点就是最大点独立集的点
    {
        if(is_ans[x])return;
        is_ans[x]=1;
        for(int i=head[x];i!=-1;i=edg[i].next)
        {
            int v=edg[i].to;
            if(v==s||v==t)continue;
    
            if(edg[i].is_match==(bool)type)dfs(v,1-type);
        }
    }
    
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&arr[i]);
    
        init();
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                int now=arr[i]^arr[j];
                if(now==(now&-now))
                {
                    addedge(i,j);
                    addedge(j,i);
                  //  printf("%d %d
    ",arr[i],arr[j]);
                }
            }
        }
    
        for(int i=1;i<=n;i++)
            if(!color[i])Bipartite_graph_coloring(i,1);//先将图划分成二分图
    
       /* for(int i=1;i<=n;i++)if(color[i]==1)printf("%d ",arr[i]);
        printf("
    ");
        for(int i=1;i<=n;i++)if(color[i]==-1)printf("%d ",arr[i]);
        printf("
    ");*/
    
        init();
    
        s=n+1,t=s+1;
        for(int i=1;i<=n;i++)
        {
            if(color[i]==1)addedge(s,i,1);
            else
                addedge(i,t,1);
    
            if(color[i]==1)
            {
                for(int j=1;j<=n;j++)
                {
                    int now=arr[i]^arr[j];
                    if(now==(now&-now))
                    {
                        addedge(i,j,1);//建边准备跑二分图匹配
                    }
                }
            }
        }
        int ans=n-dinic();
        printf("%d
    ",ans);
    
        for(int i=1;i<=n;i++)
        {
            if(color[i]==1)
            {
                for(int j=head[i];j!=-1;j=edg[j].next)
                {
                    if(edg[j].to!=s&&edg[j^1].flow)
                    {
                        edg[j].is_match=edg[j^1].is_match=true;
                        is_match_vertex[i]=is_match_vertex[edg[j].to]=true;
                    }
                    else
                    {
                        edg[j].is_match=edg[j^1].is_match=false;
                    }
                }
            }
        }
    
        for(int i=1;i<=n;i++)
        {
            if(color[i]==-1&&is_match_vertex[i]==false)
            {
                dfs(i,0);
            }
        }
    
        for(int i=1;i<=n;i++)
        {
            if(color[i]==1&&!is_ans[i]||color[i]==-1&&is_ans[i])printf("%d%c",arr[i],--ans==0 ? '
    ': ' ');
        }
        return 0;
    }
    View Code
     
     
  • 相关阅读:
    Spring初次整体了解及一篇SpringBoot的稿子。。。
    JAVA日志框架log4j和slf4j
    初学SpringBoot之三
    初学SpringBoot之二
    初学SpringBoot之一
    (转)SWITCH_ROOT
    (转)initrd和initramfs的区别
    (转)三星HDMI驱动框架解析
    (转)linux内存分析
    (转)linux中挂载IMG文件
  • 原文地址:https://www.cnblogs.com/tian-luo/p/11291132.html
Copyright © 2011-2022 走看看