关闭

wikioi 1022 覆盖

338人阅读 评论(0) 收藏 举报

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 ;
}
		


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18191次
    • 积分:586
    • 等级:
    • 排名:千里之外
    • 原创:42篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    文章存档
    最新评论