ZOJ 3646 Matrix Transformer 二分匹配,思路,经典 难度:2

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4836

因为要使对角线所有元素都是U,所以需要保证每行都有一个不同的列上有U,设(i,j)的位置是U,

以U为边,连接点i和点j+n,也即连接行点和列点,最大匹配为n则必定有解,否则必定无解

#include <cstdio>

#include <iostream>

#include <cstring>

#include <cctype>

#define clr(x,y) memset(x, y, sizeof x)

#include <cmath>

using namespace std;

const int maxn=6e2+6;

const int maxm=maxn*maxn*2;

int first[maxn];

struct edge{

    int nxt,t,f;

}e[maxm];



void addedge(int f,int t,int ind){

    e[ind].nxt=first[f];

    e[ind].t=t;

    e[ind].f=f;

    first[f]=ind;

}

int n;

char maz[maxn][maxn];



bool vis[maxn];

int match[maxn];

bool dfs(int f){

    vis[f]=true;

    for(int p=first[f];p!=-1;p=e[p].nxt){

        int t=e[p].t;

        int mch=match[t];

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

            match[t]=f;

            match[f]=t;

            return true;

        }

    }

   // printf("dfs %d no\n",f);

    return false;

}

int findmatch(){

    int ans=0;

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

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

            clr(vis,0);

            if(dfs(i))ans++;

        }

    }

    return ans;

}

void init(){

    clr(first,-1);

    clr(match,-1);

}

int main(){

    //freopen("input.txt","r",stdin);

    while(scanf("%d",&n)==1){

        init();

        int en=0;

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

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

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

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

                    addedge(i,j+n,en++);

                    addedge(j+n,i,en++);

                }

            }

        }

        int ans=findmatch();

        if(ans==n){

            puts("YES");

        }

        else {

            puts("NO");

        }

    }

    return 0;

}

 

你可能感兴趣的:(transform)