Acwing 376.机器任务 (最小点覆盖)

简介: 笔记

Acwing 376.机器任务


题意

有两台机器 A,B以及 K 个任务。


机器 A 有 N种不同的模式(模式0 ∼ N − 1 ),机器 B 有 M 种不同的模式(模式 0 ∼ M − 1)。


两台机器最开始都处于模式 0。


每个任务既可以在 A上执行,也可以在 B 上执行。


对于每个任务 i,给定两个整数a[i] 和b[i],表示如果该任务在A 上执行,需要设置模式为 a[i],如果在B 上执行,需要模式为b[i]。


任务可以以任意顺序被执行,但每台机器转换一次模式就要重启一次。


求怎样分配任务并合理安排顺序,能使机器重启次数最少。


思路

将机器A的所有模式看作左边的集合,机器B 的所有模式看作右边的集合,模式看作顶点,任务看作连接机器 A 和机器 B 的一条边,原题可以抽象成一个二分图。那么题目要求的就是,在这张二分图中最少选多少个顶点(模式),可以覆盖所有的边(任务),即最小点覆盖问题。 而我们又知道在二分图中 最小点覆盖 == 最大匹配数,所以直接用匈牙利算法求二分图的最大匹配即可。


需要注意的是,两台机器最初都处于模式0,所以不用转换模式即可将a[i] 或b[i] 为0的任务完成,所以建图时将这种情况忽略即可。


代码

// Author:zzqwtcc
// Problem: 机器任务
// Contest: AcWing
// Time:2021-10-07 14:17:44
// URL: https://www.acwing.com/problem/content/378/
// Memory Limit: 10 MB
// Time Limit: 1000 ms
#include<bits/stdc++.h>
#include<unordered_map>
// #define int long long
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define rep(i, st, ed) for (int (i) = (st); (i) <= (ed);++(i))
#define pre(i, ed, st) for (int (i) = (ed); (i) >= (st);--(i))
#define debug(x,y) cerr << (x) << " == " << (y) << endl;
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
template<typename T> inline T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> inline T lowbit(T x) { return x & -x; }
// template<typename T> T qmi(T a, T b = mod - 2, T p = mod) { T res = 1; b %= (p - 1 == 0 ? p : p - 1); while (b) { if (b & 1) { res = (LL)res * a % p; }b >>= 1; a = (LL)a * a % p; }return res % mod; }
const int N = 110;
int n,m,k;
vector<int>vec[N];
bool st[N];
int match[N];
bool find(int u){
  for(int i =0 ; i < vec[u].size();++i){
    int j =vec[u][i];
    if(st[j])continue;
    st[j] = true;
    if(match[j] == -1 || find(match[j])){
      match[j] = u;
      return true;
    }
  }
  return false;
}
void solve() {
    while(cin >> n, n){
      for(int i = 0 ;i <= 100;++i)vec[i].clear();
      memset(match,-1,sizeof match);
      cin >> m >> k;
      while(k--){
        int id,u,v;cin >> id >> u >> v;
        if(u && v)
          vec[u].push_back(v);
      }
      int res = 0;
      for(int i = 0; i <= n;++i){
        memset(st,0,sizeof st);
        if(find(i))
          res++;
      }
      for(int i = 0; i <= m;++i){
          if(match[i] == 0){
              res--;
              break;
          }
      }
      cout << res << endl;
    }
}
signed main() {
    // int _; cin >> _;
    // while (_--)
        solve();
    return 0;
}


目录
相关文章
|
8月前
|
负载均衡
acwing 3492. 负载均衡(蓝桥杯)
acwing 3492. 负载均衡(蓝桥杯)
41 0
|
6月前
|
机器学习/深度学习 存储 人工智能
第1章:算法基础【AcWing】
第1章:算法基础【AcWing】
124 0
|
8月前
|
算法 C语言 C++
LeetCode.每日一题 2427. 公因子的数目
将一个数的所有约数枚举出来,存入数组,之后再用数组中的每一个数,去看看能不能被第二个数整除,若能则答案++
41 0
|
9月前
《蓝桥杯每日一题》dfs·AcWing3502. 不同路径数
《蓝桥杯每日一题》dfs·AcWing3502. 不同路径数
39 0
|
12月前
(模拟)(枚举)acwing蓝桥杯1245. 特别数的和
(模拟)(枚举)acwing蓝桥杯1245. 特别数的和
44 0
|
人工智能 算法
AcWing算法学习第三节---高精度问题.
AcWing算法学习第三节---高精度问题.
|
存储 数据安全/隐私保护
【每日一题Day83】LC753破解保险箱 | dfs 贪心
题意要求输入一个字符串,能够打开保险柜,密码的长度为n,每位数字小于k,因此题意可以转化为找到一个最短字符串,其包含了n位k进制所有的排列组合
67 0