AcWing 376. 机器任务
题目传送门
本题 \(a[i]=0 || b[i]=0\)时可以跳过
一个任务\(i\)可以被\(A、B\)机器的两种状态\(a[i]、b[i]\)完成,将一个任务看成一条边,两种状态看成两个端点,
要完成一个任务就要从这两个点中选一个点(任务可以在\(A\)上执行也可以在\(B\)上执行),
对于所有任务就要从\(N+M-2\)个点中(不包含初始\(0\)状态)选出最少的点,覆盖所有的边(任务),
问题就变成求最小点覆盖问题(二分图中最小点覆盖等价于最大匹配数--匈牙利算法)。
#include
using namespace std;
const int N = 110;
int n, m; // A机器n种模式,B机器m种模式
int k; // k个任务
int match[N];
bool g[N][N], st[N];
bool find(int x) {
for (int i = 0; i < m; i++) //枚举右部所有点
if (!st[i] && g[x][i]) {
st[i] = true;
if (match[i] == -1 || find(match[i])) {
match[i] = x;
return true;
}
}
return false;
}
int main() {
while (cin >> n, n) {
cin >> m >> k;
memset(g, 0, sizeof g); //邻接矩阵
memset(match, -1, sizeof match); //因为本题中模式是0 ~ n-1,所以避开0,初始化-1
//建图
for (int i = 0; i < k; i++) {
int t, a, b; //任务编号,在A机器中a模式执行,在B机器中b模式执行
cin >> t >> a >> b;
if (!a || !b) continue; //因为初始时就是0状态,不需要切换,如果是可以在状态0执行的,上来就整就可以了
g[a][b] = true; // ab之间连一条边,要么在a模式中执行,要么在b模式中执行,最小点覆盖
}
//最小点覆盖 等于 最大匹配数
int res = 0;
for (int i = 0; i < n; i++) { //枚举左部每个点
memset(st, 0, sizeof st);
if (find(i)) res++;
}
//输出
cout << res << endl;
}
return 0;
}