zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第五场) maximum clique 1

    题意:给出n个不相同的数,问选出尽量多的数且任两个数字二进制下不同位数大于等于2。

    解法:能想到大于等于2反向思考的话,不难发现这是一个二分图,那么根据原图的最大团等于补图的最大独立点集,此问题就变成 任两个二进制位数相差等于1之间连边(这就是补图),然后求这个图的最大独立点集,仔细观察发现补图是个二分图。那么就可以得到最大独立点集=n-最大匹配。

    那么怎么构造一个可行方案呢?参考《算法竞赛进阶指南》的办法,1求出最大匹配  2从左边非匹配点出发跑增广路同时把路上的点标记 3最后左边非匹配点和右边匹配点组成最小点覆盖。    那么最大独立点集就是除了最小点覆盖的点啦。

    以前没写过构造最大独立点集,这题写了记录下来以免以后忘了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e3+10;
    typedef long long LL;
    int n,col[N],match[N],a[N];
    map<LL,int> mp;
    vector<int> G[N];
    
    void dfs1(int x,int c) {
        col[x]=c;
        for (int i=0;i<G[x].size();i++) {
            int y=G[x][i];
            if (!col[y]) dfs1(y,3-col[x]);
        }
    }
    
    bool vis[N],Ans[N];
    bool dfs(int x) {
        vis[x]=1;
        for (int i=0;i<G[x].size();i++) {
            int y=G[x][i];
            if (!vis[y]) {
                vis[y]=1;
                if (!match[y] || dfs(match[y])) {
                    match[y]=x; match[x]=y;  
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int i=0;i<=33;i++) mp[1LL<<i]=1;
        for (int i=1;i<=n;i++)
            for (int j=i+1;j<=n;j++)
                if (mp.count(a[i]^a[j])) G[i].push_back(j),G[j].push_back(i);
        for (int i=1;i<=n;i++)
            if (!col[i]) dfs1(i,1);         
        
        int ans=0;
        for (int i=1;i<=n;i++) {
            if (col[i]==2) continue;
            memset(vis,0,sizeof(vis));
            if (dfs(i)) ans++;
        }    
        cout<<n-ans<<endl;
        
        memset(vis,0,sizeof(vis));
        for (int i=1;i<=n;i++)
            if (col[i]==1 && !match[i]) dfs(i);
        memset(Ans,0,sizeof(Ans));    
        for (int i=1;i<=n;i++)
            if (col[i]==1 && !vis[i] || col[i]==2 && vis[i]) Ans[i]=1;
        for (int i=1;i<=n;i++)
            if (!Ans[i]) printf("%d ",a[i]);            
        return 0;
    } 
  • 相关阅读:
    Apache 虚拟主机 VirtualHost 配置
    EAX、ECX、EDX、EBX寄存器的作用
    Python中文文档 目录(转载)
    八度
    POJ 3268 Silver Cow Party (最短路)
    POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)
    2013金山西山居创意游戏程序挑战赛——复赛(1) HDU 4557 非诚勿扰 HDU 4558 剑侠情缘 HDU 4559 涂色游戏 HDU 4560 我是歌手
    HDU 4549 M斐波那契数列(矩阵快速幂+欧拉定理)
    UVA 11624 Fire! (简单图论基础)
    HDU 3534 Tree (树形DP)
  • 原文地址:https://www.cnblogs.com/clno1/p/11438094.html
Copyright © 2011-2022 走看看