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; } }
浙公网安备 33010602011771号