POJ 3041题

//题目类型:最小顶点覆盖问题
//题目大意:有一个N*N的格子,里面有-和*。一次命令可以消除某一行或某一列所有的*。请用最少的命令次数,消除所有的*。
//解题思路:最小点覆盖:在二分图中,选择最少的点,使得每一边都至少有端点被覆盖。
//Konig定理:最小点覆盖数=最大匹配数
//于是,将格子转化成左边N个点,右边N个点的二分图。边XiYj表示i,j有*。这样,只要这条边被选择,所有这一行的*都被消除,因为他们的边都一定有端点Xi.
//匈牙利算法就可以了
#include <iostream>
//#include <conio.h>
using namespace std;
#define arraysize 501
int n,k;
bool map[arraysize][arraysize];
int match[arraysize];
bool final[arraysize];
bool DFS(int p)
{
     int i;
     int temp;
     for(i=1;i<n+1;++i)
     {
         if(map[p][i] && !final[i])
         {
            final[i] = true;
            temp = match[i];
            match[i] = p;
            if(temp == 0 || DFS(temp)) return true;
            match[i] = temp;
         }
     }
     return false;
}
int mat()
{
    int i,j;
    int maxmatch = 0;
    for(i=1;i<n+1;++i)
    {
       memset(final,0,sizeof(final));
       if(DFS(i))   maxmatch++;
    }
    return maxmatch;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int i,j;
    while(cin>>n>>k)
    {
       int r,c;
       memset(map,0,sizeof(map));
       memset(match,0,sizeof(match));
       for(i=0;i<k;++i)
       {
          cin>>r>>c;
          map[r][c] = 1;
       }
       cout<<mat()<<endl;
    }
    //getch();
    return 0;
}

你可能感兴趣的:(poj)