zoukankan      html  css  js  c++  java
  • UVA 1514 Piece it together (二分图匹配)

    【题目链接】 Link

    【题目大意】

      给你一些由一块黑块和两块白块组成的L形拼图,问你是否能够拼成给出的图

    【题解】

      我们将所有的黑块拆点,拆分为纵向和横向,和周围的白块连边,
      如果能够得到完美匹配,则说明可以拼成,否则就不能

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector> 
    using namespace std;
    const int MAX_V=500000;
    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;
    }
    void clear(){for(int i=0;i<V;i++)G[i].clear();}
    const int MAX_N=500;
    char mp[MAX_N][MAX_N];
    int N,M;
    const int dx[]={1,-1,0,0};
    const int dy[]={0,0,1,-1};
    int g[MAX_N][MAX_N];
    bool check(int x,int y){return(x<0||x>=N||y<0||y>=M||mp[x][y]!='W');}
    void solve(){
        scanf("%d%d",&N,&M);
        memset(g,0,sizeof(g));
        int B=0,W=0;
        for(int i=0;i<N;i++)scanf("%s",mp[i]);
        for(int i=0;i<N;i++){   
            for(int j=0;j<M;j++){  
                if(mp[i][j]=='B')g[i][j]=B++;  
                else if(mp[i][j]=='W')g[i][j]=W++; 
            }
        }if(W!=B<<1){puts("NO");return;}
        V=W<<1;clear();
        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                if(mp[i][j]=='B'){
                    for(int k=0;k<4;k++){
                        int x=i+dx[k],y=j+dy[k];
                        if(check(x,y))continue;
                        if(dx[k])add_edge(g[i][j]+B,g[x][y]+B*2);
                        else add_edge(g[i][j],g[x][y]+B*2);
                    }
                }
            }
        }if(bipartite_matching()==W)puts("YES");  
        else puts("NO"); 
    }
    int T;
    int main(){
        scanf("%d",&T);
        while(T--)solve();
        return 0;
    }
  • 相关阅读:
    极角排序
    字符串板
    splay和lct
    国庆训练
    电子公文传输系统团队项目 确定分工
    2020课程设计——第二周进展
    在Ubuntu下使用OpenSSL搭建CA
    电子公文传输系统团队项目 需求分析
    2020课程设计——第一周进展
    2020课程设计——个人任务
  • 原文地址:https://www.cnblogs.com/forever97/p/uva1514.html
Copyright © 2011-2022 走看看