不懂该题以及二分图相关概念的可以看一下这个博客 http://blog.csdn.net/steven030143/article/details/5917969
本人初学匈牙利算法,懂得也不是很透彻,但是自己写的代码也AC了,心里还是有点小激动,关于二分图还得好好练练。。。
现在复习此题,明白是如何将问题转化为最大匹配问题的了,
建图:本代码是记录座城市的坐标,求最大匹配时,判断城市四周是否有相邻的城市,由于每座城市都要遍历一次它的四周,所以所求的匹配数会加倍,途中的最大匹配数明显为4(求得的值为8,加倍了),最大匹配中一条边覆盖两座城市,那么现在覆盖了8座城市,总共是12个城市,剩下单独的4座城市,这四座城市每座城市都需要一个圈来覆盖,则总共需要12-4*2+4=12-4=8个圈。
代码如下:
#include <iostream>
using namespace std;
#define HIGH 41
#define WIDE 11
int map[HIGH][WIDE];
int match[HIGH*WIDE];
bool visit[HIGH*WIDE];
int h,w,v_num;
struct NODE
{
int x,y;
} node[HIGH*WIDE];
bool path(int id)
{
int i;
for ( i = 0; i < v_num; i++ )
{
if (!visit[i])
{
if ( (node[i].x==node[id].x&&(node[i].y==node[id].y+1||node[i].y==node[id].y-1))
||(node[i].y==node[id].y&&(node[i].x==node[id].x+1||node[i].x==node[id].x-1)) )
{
visit[i] = true;
if ( match[i] == -1 || path(match[i]) )
{
match[i] = id;
return true;
}
}
}
}
return false;
}
int main()
{
int cas;
int i,j;
char ch;
int result;
cin >> cas;
while ( cas-- )
{
memset(map,0,sizeof(map));
memset(match,-1,sizeof(match));
cin >> h >> w;
v_num = 0;
for ( i = 0; i < h; i++ ){
for ( j = 0; j < w; j++ )
{
cin >> ch;
if ( ch == '*' )
{
node[v_num].x = j;
node[v_num].y = i;
v_num++;
}
}
}
result = 0;
for ( i = 0; i < v_num; i++ )
{
memset(visit,false,sizeof(visit));
if ( path(i) )
result++;
}
cout << v_num-result/2 << endl;
}
return 0;
}