poj3020 二分图匹配 最大独立集

这是一道水题,

这里是最大流解法,之后再补

坑在又忘了反向建边了

题意:给你二维bool数组,让你求出能用多米诺骨牌覆盖所有 1 且骨牌最少的放法(因为多米诺骨牌1*2的结构方便描述,原题没有),原本的数据是字符数组,'*'为1,'o'为0,

思路:仔细看看题会发现是上下左右只能取一个,不是那种十字星形的

取的话只能取一个点或者是两个点,要是把棋盘染色一定只能取一黑一白,总'*'也就是1的数目-黑到白的路数=孤立点+黑到白的边数=总数-最大匹配

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
char maz[62][62];
int e[500][500];
int d[4][2]={0,1,0,-1,1,0,-1,0};
int n,m;
vector <int > G[500];
bool vis[500];
void addedge(int from,int to){
    e[from][to]=1;
    G[from].push_back(to);
}
int dfs(int s){
    vis[s]=true;
    if(s==n*m+1){//printf("dfs %d ok\n",s);
    return 1;}
    for(int i=0;i<G[s].size();i++){
        if(!vis[G[s][i]]&&e[s][G[s][i]]&&dfs(G[s][i])){
            e[s][G[s][i]]=0;
            e[G[s][i]][s]=1;
          //  printf("dfs %d ok\n",s);
            return 1;
        }
    }
    //printf("dfs %d failed \n",s);
    return 0;
}
int maxflow(){
    int ans=0,f;
    while(1){
        f=dfs(n*m);
        memset(vis,0,sizeof(vis));
        if(f==0)break;
        ans+=f;
    }
    return ans;
}
void printe(){
    for(int i=0;i<m*n+2;i++){
        bool f=false;
        for(int j=0;j<m*n+2;j++){
            if(e[i][j]){printf("e[%d][%d] ",i,j);f=true;}
        }
       if(f) printf("\n");
    }
}
int main(){
    int t;
    scanf("%d",&t);
    while((t--)&&scanf("%d%d",&n,&m)==2){
        for(int i=0;i<=n*n+1;i++){G[i].clear();}
        memset(e,0,sizeof(e));

        for(int i=0;i<n;i++){
            scanf("%s",maz[i]);
        }
        int ans=0;
        int star=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(maz[i][j]=='*'){
                    star++;
                    if((i+j)&1){
                        addedge(n*m,i*m+j);//n*n s n*n+1 t
                       // printf("addedge %d %d %d %d:%d to %d\n",n,0,i,j,n*m,i*m+j);
                        for(int k=0;k<4;k++){
                            int nx=i+d[k][0];
                            int ny=j+d[k][1];
                            if(nx>=0&&nx<n&&ny>=0&&ny<m&&maz[nx][ny]=='*'){
                                addedge(i*m+j,nx*m+ny);
                         //       printf("addedge %d %d %d %d:%d to %d\n",i,j,nx,ny,i*m+j,nx*m+ny);
                            }
                        }
                    }
                    else {
                        addedge(i*m+j,n*m+1);
                        //printf("addedge %d %d %d %d:%d to %d\n",i,j,n,1,i*m+j,n*m+1);
                        for(int k=0;k<4;k++){
                            int nx=i+d[k][0];
                            int ny=j+d[k][1];
                            if(nx>=0&&nx<n&&ny>=0&&ny<m&&maz[nx][ny]=='*'){
                                addedge(i*m+j,nx*m+ny);
                                e[i*m+j][nx*m+ny]=0;
                          //      printf("addedge %d %d %d %d:%d to %d\n",i,j,nx,ny,i*m+j,nx*m+ny);
                            }
                        }
                    }
                }
            }
        }

        ans=maxflow();
        printf("%d\n",star-ans);
    }
    return 0;
}


你可能感兴趣的:(poj)