POJ 2226 Muddy Fields (二分图匹配)

【题目链接】 http://poj.org/problem?id=2226

【题目大意】

  给出一张图,上面有泥和草地,有泥的地方需要用1*k的木板覆盖,
  有草地的地方不希望被覆盖,问在此条件下需要的最少木板数目

【题解】

  我们将四周都当成草地,将每块草地拆成横向点和纵向点
  对于每一块泥地,我们将其向左和向上遇到的第一块草地连线,
  对于这个图的最小点覆盖就是答案,而最小点覆盖等于二分图的最大匹配,
  因此我们做一遍最大匹配即可

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector> 
#include <queue>
using namespace std;
const int MAX_V=10000;
int V,match[MAX_V];
vector<int> G[MAX_V];
bool used[MAX_V];
void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}
bool dfs(int v){
    used[v]=1;
    for(int i=0;i<G[v].size();i++){
        int u=G[v][i],w=match[u];
        if(w<0||!used[w]&&dfs(w)){
            match[v]=u;
            match[u]=v;
            return 1;
        }
    }return 0;
}
int bipartite_matching(){
    int res=0;
    memset(match,-1,sizeof(match));
    for(int v=0;v<V;v++){
        if(match[v]<0){
            memset(used,0,sizeof(used));
            if(dfs(v))res++;
        }
    }return res;
}
const int MAX_N=60;
char mp[MAX_N][MAX_N];
int g[MAX_N][MAX_N][2];
int T,N,M;
void init(){
	  memset(g,0,sizeof(g)); 
    for(int i=0;i<N;i++){
        scanf("%s",mp[i]);
    }
}
void solve(){
    int mark=1,cnt=0;
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(mp[i][j]=='.')g[i][j][0]=-1,cnt++;
            else g[i][j][0]=cnt,mark=1;
        }if(mark)cnt++;
    }
    for(int j=0;j<M;j++){
        mark=0;
        for(int i=0;i<N;i++){
            if(mp[i][j]=='.')cnt++;
            else g[i][j][1]=cnt,mark=1;
        }if(mark)cnt++;
    }
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++)if(~g[i][j][0]){
            add_edge(g[i][j][0],g[i][j][1]);
        }
    }V=cnt;
    printf("%d
",bipartite_matching());
    for(int i=0;i<=V;i++)G[i].clear();
}
int main(){
    while(~scanf("%d%d",&N,&M)){
        init();
        solve();
    }return 0;
}
原文地址:https://www.cnblogs.com/forever97/p/poj2226.html