D177 二分图最小点覆盖 匈牙利算法 U455932 机器任务

D177 二分图最小点覆盖 匈牙利算法 U455932 机器任务_哔哩哔哩_bilibili

 

U455932 机器任务 - 洛谷   UVA1194 Machine Schedule - 洛谷   Machine Schedule - UVA 1194 - Virtual Judge

两台机器 A、B,K 个任务。每个任务要么在 A 上以ai模式执行,要么在机器 B 上以bi模式执行。两台机器开始都处于模式 0 。

任务可以以任意顺序被执行,但每台机器转换一次模式就要重启一次。求怎样分配任务并合理安排顺序,能使机器重启次数最少。

 

二分图最小点覆盖:选出最少的点,使得每一条边的两个端点至少有一个被选中

结论:二分图中,最小点覆盖 $=$ 最大匹配数

证明:
① 最小点覆盖 $\ge$ 最大匹配数
因为最大匹配中的所有边是相互独立的,要想覆盖所有的边,至少要在每一条边上选一个点,选点数 $\ge$ 最大匹配数
② 等号可以成立

思路

每个任务要么在 A 上以 ai 模式执行,要么在机器 B 上以 bi 模式执行

A 的 n 种模式作为左部点,把 B 的 m 种模式作为右部点,每个任务作为边连接左部 ai 节点和右部 bi 节点

要完成一个任务就要从这两个点中选一个点,对于所有任务就要选出最少的点,覆盖所有的边,即求最小点覆盖

参考:D25【模板】二分图最大匹配 匈牙利算法 - 董晓 - 博客园

 

// 二分图 匈牙利算法 O(V*E)
#include<bits/stdc++.h>
using namespace std;

const int N=110;
int n,m,k,g[N][N];
int vis[N],match[N];

bool dfs(int u){
  for(int v=0; v<m; v++){ //枚举女生
    if(vis[v] || !g[u][v]) continue; //v已参与或无连边
    vis[v]=1; //记录v参与这一轮试配
    if(!match[v] || dfs(match[v])){ //v未配对或其男友可退让
      match[v]=u;
      return 1; //配对成功
    }
  }
  return 0; //配对失败
}
int main(){
  while(cin>>n,n){ //A的n种模式
    cin>>m>>k;     //B的m种模式 k个任务
    memset(g,0,sizeof g);
    memset(match,0,sizeof match);
    for(int t,a,b;k--;){
      cin>>t>>a>>b; //A上执行需要设置模式a,B上执行需要设置模式b
      if(!a||!b) continue; //模式0不需要重启
      g[a][b]=1; //模式a→模式b
    }
    
    int ans=0;
    for(int i=0; i<n; i++){ //枚举男生
      memset(vis,0,sizeof vis);
      if(dfs(i)) ans++;
    }
    cout<<ans<<endl;
  }
}

 

posted @ 2026-05-31 18:41  董晓  阅读(30)  评论(0)    收藏  举报