解题思路:
- 将每头牛对牛棚满意度依次存储
- 二分区间(区间最大为B)
- 枚举区间头,从而确定区间尾
- 进行多重匹配的边必须要先满足在区间内
AC代码:
// Test1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 1010;
int N, B;
int rk[maxn][100], cap[maxn], vis[maxn];
int match[50][maxn];
void Init() {
int x;
cin >> N >> B;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= B; j++) {
cin >> x;//第j个输入的牛棚是第j满意的
rk[i][x] = j;
}
for (int i = 1; i <= B; i++)
cin >> cap[i];
}
bool dfs(int x, int l, int r) {
for (int i = 1; i <= B; i++) {
if (l <= rk[x][i] && rk[x][i] <= r && !vis[i]) {//一定要满足在这个区间内
//其实可以借鉴如果要二分,那么不需要重新建边,要先满足在某个范围内
vis[i] = 1;
if (match[i][0] < cap[i]) {
match[i][++match[i][0]] = x;
return true;
}
for (int j = 1; j <= match[i][0]; j++)
if (dfs(match[i][j], l, r)) {
match[i][j] = x;
return true;
}
}
}
return false;
}
bool Maxmatch(int l, int r) {
int sum = 0;
memset(match, 0, sizeof(match));
for (int i = 1; i <= N; i++) {
memset(vis, 0, sizeof(vis));
if (!dfs(i, l, r)) return false;
}
return true;
}
bool check(int mid) {
for (int i = 1; i <= B; i++)
if (Maxmatch(i, i + mid))
return true;
return false;
}
void Solve() {
int lef = 0, rig = B, mid = (lef + rig) >> 1, ans;
while (lef <= rig) {
if (check(mid)) rig = mid - 1, ans = mid;
else lef = mid + 1;
mid = (lef + rig) >> 1;
}
cout << ans + 1 << endl;//题目要求
}
int main() {
Init();
Solve();
return 0;
}
ps:其实可以借鉴,如果要二分,那么不需要重新建边,先将边全部相连, 要先满足在某个范围内