POJ 2724 Purifying Machine (二分图最大独立集Hungary)

题意:迈克有一台可以净化奶酪的机器,用二进制表示净化的奶酪的编号。但是,在某些二进制串中可能包含有‘*'。例如01*100,'*'其实就代表可以取0,1两种情况--> 010100 和011100。现在由于迈克不小心,他以同样的方式弄脏了某些奶酪,问你最少用多少次操作就可以把弄脏的奶酪全净化好。(没有被弄脏过的奶酪不能净化。弄脏过的奶酪可以多次净化。)
题解:净化的时候,净化的时候每次尽量用包含*的二进制串(因为它可以净化两块奶酪)。
操作数 = 总污染数 - 2 * 最大匹配 + 最大匹配。 (代码中求出的最大匹配数是实际值的2倍)。判断二进制是否之差一位C=A^B ;  C&&((C&(C-1))==0)

#include <algorithm>
#include <iostream>
using namespace std;

#define N 2050
bool vis[N];
int num[N], match[N], link[N][N];
int m, n, cnt;

bool find_path ( int u )
{
	for ( int i = 1; i <= link[u][0]; i++ )
	{
		int v = link[u][i];
		if ( ! vis[v] )
		{
			vis[v] = true;    
		    if ( !match[v] || find_path(match[v]) )
			{
			    match[v] = u;
			    return true;
			}
		}
	}
	return false;
}

int Hungary ()
{
	int ans = 0;
	memset(match,0,sizeof(match));

	for ( int i = 1; i <= cnt; i++ )
	{
		memset(vis,0,sizeof(vis));
		if ( find_path ( i ) ) ans++;
	}
	return ans;
}

int main()
{
	char oper[12];
	int i, j, k;
	while ( scanf("%d %d",&n, &m) && (m+n) )
	{
		cnt = 0;
		memset(link,0,sizeof(link));
		memset(num,0,sizeof(num));

		for ( i = 1; i <= m; i++ )
		{
			scanf("%s",oper);
			cnt++; k = -1;
			for ( j = 0; j < n; j++ )
			{
				if ( oper[j] == '*' ) k = j;
				else num[cnt] |= ((oper[j]-'0')<<j);
			}
			if ( k != -1 )
			{
				cnt++;
				num[cnt] = (num[cnt-1] | (1<<k));
			}
		}

		sort(num+1,num+1+cnt);
		num[0] = -1;
		for ( j = 0, i = 1; i <= cnt; i++ )
		{
			if ( num[j] != num[i] )
				num[++j] = num[i];
		}
		cnt = j;

		for ( i = 1; i <= cnt; i++ )
		{
			for ( j = 1; j <= cnt; j++ )
			{
				int t = num[i] ^ num[j];
				if ( t && ((t&(t-1)) == 0) )
				{
				    link[i][0]++;
				    link[i][link[i][0]] = j;
				}
			}
		}
		printf("%d\n",cnt-Hungary()/2);
	}
	return 0;
}

			


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值