ICPC Pacific Northwest Regional Contest 2016 - Maximum Islands(二分图最大独立集)

You are mapping a faraway planet using a satellite. 

Your satellite has captured an image of the planet’s surface. The photographed section can bemodeled as a grid. Each grid cell is either land, water, or covered by clouds. Clouds mean that thesurface could either be land or water, but we can’t tell. 

An island is a set of connected land cells. Two cells are considered connected if they share an edge. 

Given the image, determine the maximum number of islands that is consistent with the giveninformation.

Input

The first line of input contains two space-separated integers n and m (1 ≤ n, m ≤ 40).Each of the next n lines contains m characters, describing the satellite image. Land cells aredenoted by ‘L’, water cells are denoted by ‘W’, and cells covered by clouds are denoted by ‘C’.

Output

Print, on a single line, a single integer indicating the maximum number of islands that is consistentwith the given grid.

样例输入复制

5 4
LLWL
CCCC
CCCC
CCCC
LWLL

样例输出复制

8

题目链接:点击查看

扫描二维码关注公众号,回复: 11366150 查看本文章

题目大意:给出一张大小为 n * m 的卫星俯瞰图,只由 ' L ' , ' W ' , ' C ' 三个组成,L 代表陆地,W 代表海洋, C 代表云朵,云朵下面可能是海洋也可能是陆地,现在问最多可能有多少个岛屿

一个陆地连通块组成一个岛屿

题目分析:首先对于已经给出的陆地 L ,我们最优的做法是将所有与 L 相邻的 C 全部变为 W ,这样的话无论剩下的 C 如何操作,都不会对已经固定的 L 产生影响了,此时通过 bfs 或者 dfs 可以很轻松的求出当前岛屿的数量,记为 ans1,那么这张图还可以为岛屿数量做出贡献的就是 C 的连通块了,因为数据范围比较小,又因为是要求全局最优的问题,所以不难想到求出 C 的最大独立集,记最大独立集的个数为 ans2,那么最终的答案就是 ans1 + ans2 了,当然肯定不能直接求一般图的最大独立集,最多一共有 1600 个点,时间复杂度肯定是顶不住的,因为是在 n * m 的矩阵中,可以想到奇偶拆点,因为奇坐标点和偶坐标点一定是没有边相连的,将问题转换为二分图的最大独立集后,建好图直接跑匈牙利就不难得到 ans2 了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=50;

const int b[4][2]={0,1,0,-1,1,0,-1,0};

char maze[N][N];

int n,m,cnt1,cnt2,num1[N][N],num2[N][N];

vector<int>node[1000];

bool vis[1000];

int match[1000];

bool dfs(int x)
{
	for(int i=0;i<node[x].size();i++)
	{
		int y=node[x][i];
		if(!vis[y])
		{
			vis[y]=true;
			if(!match[y]||dfs(match[y]))
			{
				match[y]=x;
				return true;
			}
		}
	}
	return false;
}

void build()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(maze[i][j]=='C')
			{
				if((i+j)&1)
					num1[i][j]=++cnt1;
				else
					num2[i][j]=++cnt2;	
			}
	for(int x=1;x<=n;x++)//建边
		for(int y=1;y<=m;y++)
		{
			if(maze[x][y]!='C')
				continue;
			for(int k=0;k<4;k++)
			{
				int xx=x+b[k][0];
				int yy=y+b[k][1];
				if(xx<=0||yy<=0||xx>n||yy>m)
					continue;
				if(maze[xx][yy]!='C')
					continue;
				if((x+y)&1)
					node[num1[x][y]].push_back(num2[xx][yy]);
				else
					node[num1[xx][yy]].push_back(num2[x][y]);
			}
		}	
}

void DFS(int x,int y)
{
	maze[x][y]='*';
	for(int i=0;i<4;i++)
	{
		int xx=x+b[i][0];
		int yy=y+b[i][1];
		if(xx<=0||yy<=0||xx>n||yy>m)
			continue;
		if(maze[xx][yy]=='L')
			DFS(xx,yy);
	}
}

int solve()
{
	int ans=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(maze[i][j]=='L')
			{
				DFS(i,j);
				ans++;
			}
	return ans;
}

void init()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(maze[i][j]=='C')
				for(int k=0;k<4;k++)
				{
					int xx=i+b[k][0];
					int yy=j+b[k][1];
					if(xx<=0||yy<=0||xx>n||yy>m)
						continue;
					if(maze[xx][yy]=='L')
					{
						maze[i][j]='*';
						break;
					}
				}
}

int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%s",maze[i]+1);
	init();
	build();
	int ans=0;
	for(int i=1;i<=cnt1;i++)
	{
		memset(vis,false,sizeof(vis));
		if(dfs(i))
			ans++;
	}
	printf("%d\n",cnt1+cnt2-ans+solve());









    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106892783