给定一个N行M列的棋盘,已知某些格子禁止放置。
问棋盘上最多能放多少个不能互相攻击的車。
車放在格子里,攻击范围与中国象棋的“車”一致。
输入格式
第一行包含三个整数N,M,T,其中T表示禁止放置的格子的数量。
接下来T行每行包含两个整数x和y,表示位于第x行第y列的格子禁止放置,行列数从1开始。
输出格式
输出一个整数,表示结果。
数据范围
1≤N,M≤200
输入样例:
8 8 0
输出样例:
8
题意:如题 |
思路:
观察車攻击的规则,最后的棋盘状态肯定是每个車占一行和一列,换句话说,行和列必须是一一对应才满足(一个行坐标对应一个列坐标)。那么这就符合二分图的性质了。我们把行坐标集合看成左部图,列坐标集合看成右部图,这个时候就是求一个最大匹配问题。
运用匈牙利算法,直观的逻辑就是,遍历每一行,枚举每个列位置能不能放——若没放过肯定可以,若放过,看看之前用到这列的那一行能不能移开(dfs(pre[y])),可以就ans++ 。
AC代码:
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f