UVALive 5903 Piece it together 二分匹配,拆点 难度:1

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3914

对L研究可以发现

相当于黑-横白,黑-纵白,每个黑白都要被匹配到,其中黑的横纵各两次,

很自然的想到拆点,黑点拆成专门和横白连接的,专门和纵白连接的,

如果2*黑==白数,运行一次二分匹配算法,匹配数==白数则为可行,剩下的都不可行

#include <cstdio>

#include <cstring>

#include <vector>

using namespace std;

const int dx[4]={0,0,1,-1};

const int dy[4]={1,-1,0,0};

char maz[600][601];

int ind[600][600];

int n,m;

bool inmaz(int x,int y){return 0<=x&&x<n&&0<=y&&y<m;}

struct pnt{

        int x,y;

        pnt(){x=y=0;}

        pnt(int x,int y){this->x=x;this->y=y;}

};

pnt pw[600*600],pb[600*600];

int lenw,lenb;

int e[2*600*600][8];

int len[2*600*600];



int mch[2*600*600];

bool used[2*600*600];



bool dfs(int s){

        used[s]=true;

        for(int i=0;i<len[s];i++){

                int t=e[s][i];

                if(mch[t]==-1||(!used[mch[t]]&&dfs(mch[t]))){

                        mch[t]=s;

                        mch[s]=t;

                        return true;

                }

        }

        return false;

}



int match(){

        memset(mch,-1,sizeof(int)*2*lenw);

        int res=0;

        for(int i=0;i<lenw*2;i++){

                if(mch[i]==-1){

                        memset(used,false,2*lenw);

                        if(dfs(i)){

                                res++;

                        }

                }

        }

        return res;

}



int main(){

        int T;

        scanf("%d",&T);

        while(T--){

                scanf("%d%d",&n,&m);

                lenb=lenw=0;

                memset(len,0,sizeof(len));

                memset(ind,0,sizeof(ind));

                for(int i=0;i<n;i++)scanf("%s",maz[i]);

                for(int i=0;i<n;i++){

                        for(int j=0;j<m;j++){

                                if(maz[i][j]=='W'){

                                        ind[i][j]=lenw;

                                        pw[lenw++]=pnt(i,j);

                                }

                                else if(maz[i][j]=='B'){

                                        ind[i][j]=lenb;

                                        pb[lenb++]=pnt(i,j);

                                }

                        }

                }

                if(lenw!=lenb*2){

                        puts("NO");

                        continue;

                }

                for(int i=0;i<lenb;i++){

                        int x=pb[i].x,y=pb[i].y;

                        for(int j=0;j<2;j++){

                                int txj=x+dx[j],tyj=y+dy[j];

                                if(!inmaz(txj,tyj)||maz[txj][tyj]!='W')continue;

                                int indj=ind[txj][tyj],hor=lenw+2*i+1;



                                e[indj][len[indj]++]=hor;

                                e[hor][len[hor]++]=indj;

                        }

                        for(int k=2;k<4;k++){

                                int txk=x+dx[k],tyk=y+dy[k];

                                if(!inmaz(txk,tyk)||maz[txk][tyk]!='W')continue;

                                int indk=ind[txk][tyk],gra=lenw+2*i;

                                e[indk][len[indk]++]=gra;

                                e[gra][len[gra]++]=indk;

                        }

                }

                int res=match();

                if(res!=lenw)puts("NO");

                else puts("YES");

        }

        return 0;

}

  

你可能感兴趣的:(live)