转化成求最小路径覆盖。
根据公式,有向图最小路径覆盖 = N - 最大二分匹配
无向图最小路径覆盖 = N - 最大二分匹配/2
本题两个城市家之间应属无向图。
一个城市看做一个节点,V1为所有节点,V2为所有节点的克隆。|V1|=|V2|=N。
求出V1和V2之间最大二分匹配,代入公式即可。
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
char data[41][20];
int index[41][20];
bool graph[401][401];
bool visit[401];
int link[401];
int row,col;
int n;
int bias_i[] = {-1,1,0,0};
int bias_j[] = {0,0,-1,1};
bool find(int i){
for(int j = 1;j<=n;++j){
if(graph[i][j] && !visit[j]){
visit[j] = 1;
if(link[j]==0 || find(link[j])){
link[j] = i;
return true;
}
}
}
return false;
}
int main(){
int t;
cin>>t;
while(t--){
memset(index,0,sizeof(index));
memset(link,0,sizeof(link));
memset(graph,0,sizeof(graph));
cin>>row>>col;
char tmp[5];
gets(tmp);
for(int i=1;i<=row;++i)
gets(data[i]+1);
n = 1;
for(int i=1;i<=row;++i)
for(int j=1;j<=col;++j)
if(data[i][j]=='*')
index[i][j] = n++;
--n;
for(int i=1;i<=row;++i){
for(int j=1;j<=col;++j){
if(index[i][j]>0){
for(int k=0;k<4;++k){
if(index[i+bias_i[k]][j+bias_j[k]]>0)
graph[index[i][j]][index[i+bias_i[k]][j+bias_j[k]]] = true;
}
}
}
}
int m = 0;
for(int i=1;i<=n;++i){
memset(visit,0,sizeof(visit));
if(find(i))
++m;
}
cout<<n-m/2<<endl;
}
}