zoukankan      html  css  js  c++  java
  • poj 2724 二分图最大匹配

    题意:

    会给出M个串,我们要做的就是将这M个串给清除了。对于任意两个串,若二进制形式只有一位不一样,那么这两个串可以在一次操作消除,否则每个操作只能消除一个串。

    3 3

    *01

    100

    011

    可以代表的串是

    001

    101

    100

    011

    那么我们可以先用 10*把 101 和 100 消除了,再用 0*1把001 和 011 消除了。故操作次数为 2。

    解题思路:

    我们可以将所有的串先化为整数,并去重。然后对二进制形式只有一位不一样的两个数,我们由含有偶数个1的数向含有奇数个1的数连边,这样就确保了一定是二分图,因为不存在同含奇数个1或同含偶数个1 的数只相差一位。最后进行求最大匹配,既是我们可以省去的操作数。所以我们求得最大独立集才是最终答案。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define Maxn 1200
    using namespace std;
    int graphic[Maxn][Maxn],vi[Maxn],match[Maxn],n,m,ans[Maxn],e;
    int dfs(int u)//匈牙利算法
    {
        int i;
        for(i=1;i<=e;i++)
        {
            if(!vi[i]&&graphic[u][i])
            {
                vi[i]=1;
                if(match[i]==-1||dfs(match[i]))
                {
                    match[i]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main()
    {
        int i,j,k,Case=1,a,b,num1,num2,Exp[13];
        char str[11];
        Exp[0]=1;
        for(i=1;i<=12;i++)
            Exp[i]=Exp[i-1]*2;
        while(scanf("%d%d",&n,&m),n||m)
        {
            memset(match,-1,sizeof(match));
            memset(graphic,0,sizeof(graphic));
            memset(ans,0,sizeof(ans));
            e=0;
            for(i=1;i<=m;i++)
            {
                scanf("%s",&str);
                num1=0;num2=-1;
                for(j=n-1;j>=0;j--)
                {
                    if(str[j]!='*')
                        num1+=Exp[n-j-1]*(str[j]-'0');
                    else
                        num2=Exp[n-j-1];
                }
                ans[++e]=num1;
                if(num2!=-1)
                    ans[++e]=num1+num2;
            }
            int num=1;
            sort(ans+1,ans+e+1);//排完序后进行去重
            for(i=2;i<=e;i++)
                if(ans[i]!=ans[num])
                    ans[++num]=ans[i];
            e=num;
            for(i=1;i<=e;i++) 
            {
                for(j=i+1;j<=e;j++)
                {
                    int temp=(ans[i]^ans[j]);//找出不同位
                    if((temp&(temp-1))==0)//若不同位只有一位,则为0
                    {
                        temp=ans[i];
                        num=0;
                        while(temp)//求出二进制数1的个数
                        {
                            num++;
                            temp=temp&(temp-1);
                        }
                        if(num%2==0)//判断1的个数是奇数还是偶数
                            graphic[i][j]=1;
                        else
                            graphic[j][i]=1;
                    }
                }
            }
            num=0;
            for(i=1;i<=e;i++)
            {
                memset(vi,0,sizeof(vi));
                if(dfs(i))
                    num++;
            }
            printf("%d
    ",e-num);
        }
        return 0;
    }
  • 相关阅读:
    Roce ofed 环境搭建与测试
    Ubuntu 1804 搭建NFS服务器
    Redhat 8.0.0 安装与网络配置
    Centos 8.1 安装与网络配置
    SUSE 15.1 系统安装
    VSpare ESXi 7.0 基本使用(模板、iso、SRIOV)
    VSpare ESXi 7.0 服务器安装
    open SUSE leap 15.1 安装图解
    KVM虚拟机网卡连接网桥
    GitHub Action一键部署配置,值得拥有
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3194416.html
Copyright © 2011-2022 走看看