1. 程式人生 > >匈牙利演算法(最小點覆蓋)poj3041

匈牙利演算法(最小點覆蓋)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號座位又坐了,因此加以標記。表示幾號座位是準備給騰出來的,不能在騰的過程中讓別人坐了