D178 二分图最小点覆盖 匈牙利算法 P6062 [USACO05JAN] Muddy Fields G
D178 二分图最小点覆盖 匈牙利算法 P6062 [USACO05JAN] Muddy Fields G_哔哩哔哩_bilibili
P6062 [USACO05JAN] Muddy Fields G - 洛谷
牧场是一个 R×C 的矩形,其中 1≤R,C≤50。每块木板的宽度为 1 个单位,长度任意,每个板必须放置在平行于牧场的泥地里。
求使用最少的木板覆盖所有的泥地。一个木板可以重叠在另一个木板上,但是不能放在草地上。
思路
根据贪心思想,给连续泥地放一块木板,即连续泥地的坐标使用相同的木板编号
木板分两类:横放的、竖放的,横放的木板编号看做左部点,竖放的木板编号看做右部点,对重叠木板编号从左向右连边
题目就是选出最少的端点(木板),覆盖所有的边,即最小点覆盖,这样,每块泥地都被一块或两块木板盖住

参考:D177 二分图最小点覆盖 匈牙利算法 U455932 机器任务 - 董晓 - 博客园
// 二分图 匈牙利算法 O(V*E) #include<bits/stdc++.h> using namespace std; const int N=1255; vector<int> e[N]; int n,m,sx,sy,ans; char a[55][55]; int x[55][55],y[55][55]; int vis[N],match[N]; bool dfs(int u){ for(auto v:e[u]){ //竖向编号是右部点 if(vis[v]) continue; //v已参与 vis[v]=1; //记录v参与 if(!match[v]||dfs(match[v])){ //v没配对或v的男友可退让 match[v]=u; //记录v的男友u return 1; //配对成功 } } return 0; //配对失败 } int main(){ cin>>n>>m; for(int i=1;i<=n;++i){ cin>>a[i]+1; //输入一行字符 for(int j=1;j<=m;++j){ if(a[i][j]=='*'){ x[i][j]=(a[i][j-1]=='*'?x[i][j-1]:++sx); //横向木板编号 y[i][j]=(a[i-1][j]=='*'?y[i-1][j]:++sy); //竖向木板编号 e[x[i][j]].push_back(y[i][j]); //木板横向编号→竖向编号连边 } } } for(int i=1;i<=sx;i++){ //横向编号是左部点 memset(vis,0,sizeof vis); ans+=dfs(i); //累加配对数 } cout<<ans; return 0; }
浙公网安备 33010602011771号