zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Linq语句jion on后指定多个条件
    sql判断日期是否为当前季度
    Linq to json
    .net压缩文件夹
    .net代码修改webconfig
    .net正则IP加端口,并返回IP加端口
    获取汉字拼音的首字母(获取助记码)
    .net获取程序根目录
    关闭IPV6
    mysql查看日志
  • 原文地址:https://www.cnblogs.com/forever97/p/poj2226.html
Copyright © 2011-2022 走看看