首页 > 代码库 > BZOJ 2150 部落战争 最小路径覆盖 二分图最大匹配
BZOJ 2150 部落战争 最小路径覆盖 二分图最大匹配
题目大意:给出一张地图,一个军队要征战整个土地。一块土地只能经过一次,有X的地方不能走,军队只会走R*C个格子,只会向下走,问最少需要多少军队能够征战所有的土地。
思路:这个是前几天考试的题,今天居然发现时BZ的原题,还好当时A掉了。。。
看到每个土地只能经过一次就想到了网络流什么的,再一想想好像是最小路径覆盖啊,然后拆点,建图,Hungary,二分图最小路径覆盖=点数-最大匹配,没了。。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 20010 using namespace std; int m,n,r,c; char src[200][200]; int num[200][200],cnt; int head[MAX],total; int _next[MAX],aim[MAX]; bool v[MAX]; int paired[MAX]; inline void Add(int x,int y) { _next[++total] = head[x]; aim[total] = y; head[x] = total; } bool Hungary(int x) { for(int i = head[x]; i; i = _next[i]) { if(!v[aim[i]]) { v[aim[i]] = true; if(!paired[aim[i]] || Hungary(paired[aim[i]])) { paired[aim[i]] = x; return true; } } } return false; } int main() { cin >> m >> n >> r >> c; for(int i = 1; i <= m; ++i) { scanf("%s",src[i] + 1); for(int j = 1; j <= n; ++j) if(src[i][j] == '.') num[i][j] = ++cnt; } for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) { if(!num[i][j]) continue; if(i + r > 0 && j + c > 0 && num[i + r][j + c]) Add(num[i][j],num[i + r][j + c] + cnt); if(i + c > 0 && j + r > 0 && num[i + c][j + r]) Add(num[i][j],num[i + c][j + r] + cnt); if(i + r > 0 && j - c > 0 && num[i + r][j - c]) Add(num[i][j],num[i + r][j - c] + cnt); if(i + c > 0 && j - r > 0 && num[i + c][j - r]) Add(num[i][j],num[i + c][j - r] + cnt); } int ans = 0; for(int i = 1; i <= cnt; ++i) { memset(v,false,sizeof(v)); ans += Hungary(i); } cout << cnt - ans << endl; return 0; }
BZOJ 2150 部落战争 最小路径覆盖 二分图最大匹配
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。