題意:在大海里有一些石油 ‘#’表示石油, ‘.’表示水,有我的有一個工具能夠回收這些石油,不過只能回收1*2大小的石油塊,裏面不能含有海水,要不就沒辦法使用了,求出來最多能回收多少塊石油
分析:先把數據處理一下,給每一點石油都進行編號,而後查找一下四周聯合是否能組成石油塊,能的話就鏈接,由於一點有可能即在左邊又在右邊,因此最後的結果應該除去 2
#include<stdio.h>
#include<
string.h>
#include<queue>
using
namespace std;
const
int MAXN =
40005;
///
處理後點的個數
const
int MAXM =
605;
///
原圖大小
const
int oo = 1e9+
7;
char G[MAXM][MAXM];
int N;
///
保存原圖
int Index[MAXM][MAXM];
///
給石油點編號
struct Edge{
int v, next;}e[MAXN*
4];
int Head[MAXN], cnt;
///
處理後的邊
int Mx[MAXN], My[MAXN];
///
記錄與之匹配的點
int used[MAXN], dx[MAXN], dy[MAXN];
///
dx,dy記錄BFS後的層次
int depth, NX;
///
寬搜的深度,和點的個數
void InIt()
{
///
初始化
NX = cnt =
0;
memset(Head, -
1,
sizeof(Head));
memset(Mx,
false,
sizeof(Mx));
memset(My,
false,
sizeof(My));
}
void AddEdge(
int u,
int v)
{
///
添加邊
e[cnt].v = v;
e[cnt].next = Head[u];
Head[u] = cnt++;
}
bool BFS()
{
///
廣搜求出層次,而且判斷是否有增廣路存在
queue<
int> Q;
depth = oo;
memset(dx,
false,
sizeof(dx));
memset(dy,
false,
sizeof(dy));
for(
int i=
1; i<=NX; i++)
{
if( Mx[i] ==
false )
{
dx[i] =
true;
Q.push(i);
}
}
while(Q.size())
{
int u = Q.front(); Q.pop();
if( dx[u] > depth )
break;
///
已經發現上層存在增廣路
for(
int j=Head[u]; j!=-
1; j=e[j].next)
{
int v = e[j].v;
if( dy[v] ==
false )
{
dy[v] = dx[u] +
1;
if(My[v] ==
false)
depth = dy[v];
else
{
dx[ My[v] ] = dy[v] +
1;
Q.push( My[v] );
}
}
}
}
return depth != oo;
}
bool DFS(
int i)
{
for(
int j=Head[i]; j!=-
1; j=e[j].next)
{
int v = e[j].v;
if( used[v] ==
false && dx[i] == dy[v]-
1 )
{
used[v] =
true;
///
開始忘記置爲true,錯了一次
if( My[v] && dy[v] == depth )
continue;
if( !My[v] || DFS(My[v]))
{
My[v] = i;
Mx[i] = v;
return
true;
}
}
}
return
false;
}
int Karp()
{
int ans =
0;
while( BFS() ==
true )
{
memset(used,
false,
sizeof(used));
for(
int i=
1; i<=NX; i++)
{
if( !Mx[i] && DFS(i) )
ans++;
}
}
///
由於點同時在兩邊,因此會重複一次,結果應該出去 2
return ans /
2;
}
int main()
{
int i, j, T, t=
1;
scanf(
"
%d
", &T);
while(T--)
{
scanf(
"
%d
", &N);
InIt();
for(i=
0; i<N; i++)
{
scanf(
"
%s
", G[i]);
for(j=
0; j<N; j++)
{
if(G[i][j] ==
'
#
')
{
///
購置關係圖
Index[i][j] = ++NX;
///
給石油編號
if(j !=
0 && G[i][j-
1] ==
'
#
')
{
///
與左邊的能夠匹配
AddEdge(Index[i][j], Index[i][j-
1]);
AddEdge(Index[i][j-
1], Index[i][j]);
}
if(i !=
0 && G[i-
1][j] ==
'
#
')
{
///
與上面的能夠匹配
AddEdge(Index[i][j], Index[i-
1][j]);
AddEdge(Index[i-
1][j], Index[i][j]);;
}
}
}
}
int ans = Karp();
printf(
"
Case %d: %d\n
", t++, ans);
}
return
0;
}工具