wikioi 1022 覆盖

http://wikioi.com/problem/1022/

一道二分图匹配,关键在于怎么建边,由题覆盖的为2个相连的陆地,我们可以看作是一块陆地和另一块陆地进行了匹配

于是就可以找到一个陆地,把这和四周的陆地进行加边,接下来就是匹配了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;const int maxn = 40000+100 ;
int n , m , K ;
int  tot , clock_vis, res = 1;
int head[maxn];
int vis[maxn];
int lin[maxn];
int dx[] = {0 , 0 , -1 , 1} ;
int dy[] = {1 , -1 , 0 , 0} ;
struct node{
	int next,v;
}e[maxn] ;
void add(int u,int v) {
	e[tot].v = v ;
	e[tot].next = head[u] ;
	head[u] = tot++ ;
}
bool find(int u) {
	for(int i = head[u] ; i != -1 ; i = e[i].next) {
		int v = e[i].v ;
		if(vis[v] == clock_vis) continue ;
		vis[v] = clock_vis ;//时间标记
		if(!lin[v] || find(lin[v])) {
			lin[v] = u ;
			return true ;
		}
	}
	return false ;
}

int main() {
	scanf("%d%d%d",&n,&m,&K) ;
	int x1 , y1 ;
	for(int i = 0 ; i < K ; i++) {
		scanf("%d%d",&x1,&y1) ;
		x1-- ; 
		y1-- ;
		vis[x1*m+y1] = -1 ;//一维保存坐标
	}
	for(int i = 0 ; i < n ; i++) {
		for(int j = (i%2) ; j < m ; j+=2) if(vis[i*m+j] != -1){
			head[res] = -1;
			for(int k = 0 ; k <=3 ; k++) {
				int nx = i + dx[k] ;
				int ny = j + dy[k] ;
				if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue ;
				if(vis[nx*m+ny] == -1) continue ;
				add(res, nx*m+ny) ;//加边
			}
			res++ ;//记录陆地数
		}
	}
	int ans = 0 ;
	for(int i = 1 ; i < res ; i++){//二分匹配
		clock_vis= i ;
		if(find(i)) ans++ ;
	}
	printf("%d",ans) ;
	return 0 ;
}
		


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值