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;
    }
  • 相关阅读:
    前端js(一)
    前端CSS
    前端HTML
    视图等
    Navicat使用
    查询语句
    SpringBoot不能直接访问templates下的静态资源
    Mybatis什么时候用${}
    thymeleaf使用restul风格URL
    SpringBoot使用PageHelper
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3194416.html
Copyright © 2011-2022 走看看