Problem Address:http://poj.org/problem?id=3020
【前言】
第一次交了WA。
但是不知道哪里错了。
后来改啊改啊交了,A了。
验证了之后发现只是第一次没注意好。
原来的模板为连接设置为0,标号必须从1开始。然后改的时候却改不全。
【思路】
以每个点为顶点,建立二分图。
对于某个‘*’,如果其邻点也为‘*‘,则建立一条边。
然后求二分图的最大匹配。
答案为 匹配数/2+未匹配数,或者为 ’*’的总数-匹配数/2。两者是等价的。
此外还要注意图需要开到400*400以上,因为题目要求1<=h<=40,0<w<=10。
【代码】
#include <iostream>
using namespace std;
const int maxn = 400;
bool g[maxn+5][maxn+5];
bool y[maxn+5];
int link[maxn+5];
char map[45][15];
bool find(int v, int m)
{
int i;
for(i=1; i<=m; i++)
{
if(g[v][i] && !y[i])
{
y[i]=true;
if(link[i]==0 || find(link[i],m))
{
link[i]=v;
return true;
}
}
}
return false;
}
int main()
{
int t;
int h, w;
int i, j;
int temp;
int ta, tb;
scanf("%d", &t);
while(t--)
{
scanf("%d %d", &h, &w);
memset(g, false, sizeof(g));
memset(link, 0, sizeof(link));
for (i=0; i<h; i++)
scanf("%s", map[i]);
ta = tb = 0;
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
if (map[i][j]=='*')
{
ta++;
temp = i*w + j + 1;
if (i-1>=0 && map[i-1][j]=='*') g[temp][temp-w] = true;
if (i+1<h && map[i+1][j]=='*') g[temp][temp+w] = true;
if (j-1>=0 && map[i][j-1]=='*') g[temp][temp-1] = true;
if (j+1<w && map[i][j+1]=='*') g[temp][temp+1] = true;
}
}
}
temp = h*w;
for(i=1; i<=temp ; i++)
{
for (j=0; j<=temp; j++)
y[j] = false;
if(find(i, temp))
tb++;
}
printf("%d\n", ta-tb/2);
}
return 0;
}