匈牙利算法(最小点覆盖)poj3041

题目意思是一次可以毁掉一行或者一列,要求至少毁多少次才能将图上的x都消灭掉。

简单的解释一下最小点覆盖:在图中用最少的点,覆盖图中所有的边

将每一行或者列想象成点,每个x想象成一条边,于是此题很自然的转换成为了最小点覆盖问题。

而二分图的最小点覆盖数 = 二分图的最大匹配。

于是就用匈牙利算法求这个图的最大匹配就好啦。

用人和座位分别表示二分图的x集和y集,于是匈牙利算法大概每一趟过程可以描述成以下形式

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
int used[10004];//注释1
 vector<int> map[504];//用二维向量模拟邻接表
int per[10004];// per[x]的意思是x号座位上坐的是谁
int n, m;
bool find(int x);
int main()
{
   int ans = 0;
   scanf("%d%d",&n,&m);
   int h,l;
   for(int i=0; i<m; i++)
   {
   	 scanf("%d%d",&h,&l);
   	 map[h].push_back(l);
   }
   for(int i=1; i<=n; i++)
   {
   	 memset(used,0,sizeof(used));
   	 if(find(i) )
   	 ans++;
   }
   printf("%d",ans);
   return 0;
}
bool find(int x){
	for(int i=0; i<map[x].size(); i++)//遍历x号老哥能坐的所有座位
	{

		if( !used[map[x][i]] ) //注释1
		{
		  used[map[x][i]] = 1;

		  if( per[map[x][i]] == 0 || find(per[map[x][i]]))
		  {
		   per[map[x][i]] = x;
		   return true;
	      }
	    }
	}
	return false;
}

注释1的解释:

四号大哥只能坐3号位置,为了防止一个一个腾座位的时候,有人将3号座位又坐了,因此加以标记。表示几号座位是准备给腾出来的,不能在腾的过程中让别人坐了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值