Description
Input
Output
Sample Input
1 6 ...... .##... .##... ....#. ....## ......
Sample Output
Case 1: 3
思路:
这道题的将模型抽象化之后就是一个二分匹配,其实这道题的难点就是将模型抽象出来,也就是建一个二分图,建图方法自己看代码
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int ma[700][700],ss[700][700];
char f[700][700];
int n;
int a[700],b[700];
bool use[700];
int sum;
int fin(int id)
{
int i;
for(i=1;i<sum;i++)
{
if(use[i]==false&&ma[id][i]==1)
{
use[i]=true;
if(fin(a[i])||a[i]==0)
{
a[i]=id;
return 1;
}
}
}
return 0;
}
int main()
{
int i,j;
int k;
int g;
scanf("%d",&k);
for(g=1;g<=k;g++)
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%s",f[i]);
sum=1;
memset(ss,0,sizeof(ss));
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(f[i][j]=='#')
{
ss[i][j]=sum++; //给每个点一个标号
}
}
}
memset(ma,0,sizeof(ma));
建图,将图建委无向图
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(f[i][j]=='#')
{
if(i<(n-1)&&f[i+1][j]=='#')
{
ma[ss[i][j]][ss[i+1][j]]=1;
ma[ss[i+1][j]][ss[i][j]]=1;
}
if(j<(n-1)&&f[i][j+1]=='#')
{
ma[ss[i][j]][ss[i][j+1]]=1;
ma[ss[i][j+1]][ss[i][j]]=1;
}
}
}
}
int cnt=0;
memset(a,0,sizeof(a));
for(i=1;i<sum;i++)
{
memset(use,false,sizeof(use));
if(fin(i))
cnt++;
}
printf("Case %d: %d\n",g,cnt/2); //因为为无向图,所以说要初二
}
}
///
这是我在网上找到别人的用临街表做的这道题,主要是临街表在二分匹配上的应用这个我需要熟悉一下
//296MS 4576K
#include<stdio.h>
#include<string.h>
#define MAX 601
struct Edge
{
int to,next;
}edge[MAX*MAX];
int head[MAX*MAX],tol;
void add(int a,int b)
{
edge[tol].to = b;
edge[tol].next = head[a];
head[a] = tol ++;
}
char map[MAX][MAX];
int sum,QQ[MAX][MAX];
int vis[2][2]={{1,0},{0,1}};
int link[MAX*MAX],flag[MAX*MAX];
bool dfs(int u)
{
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(!flag[v])
{
flag[v] = 1;
if(link[v] == -1 || dfs(link[v]))
{
link[v] = u;return true;
}
}
}
return false;
}
int match()
{
int ans = 0;
memset(link,-1,sizeof(link));
for(int u = 0; u < sum; u ++)
{
memset(flag,0,sizeof(flag));
if(dfs(u)) ans ++;
}
return ans/2;
}
int main()
{
int i,j;
int T,N;
scanf("%d",&T);
for(int cas = 1; cas <= T; cas ++)
{
tol = 0;
sum = 0;
memset(head,-1,sizeof(head));
scanf("%d",&N);
for(i = 0; i < N; i ++,getchar())
scanf("%s",map[i]);
//建图
for(i = 0; i < N; i++)
for(j = 0; j < N; j ++)
if(map[i][j] == '#')
QQ[i][j] = sum++;//map[i][j] = sum ++ +'0';这样不可以,如果超过9,10这个不是一个字符啦....只能借助一个数组
for(i = 0; i < N; i ++)
for(j = 0; j < N; j ++)
{
if(map[i][j] != '.')
for(int k = 0; k < 4; k ++)
{
int x = i + vis[k][0],y = j + vis[k][1];
if(y >= 0 && y < N && x >= 0 && x < N && map[x][y] != '.')// 等价map[x][y] == '#'
add(QQ[i][j], QQ[x][y]),add(QQ[x][y], QQ[i][j]);
}
}
printf("Case %d: %d\n",cas,match());
}
return 0;
}