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
",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;
}
原文地址:https://www.cnblogs.com/xuesu/p/4509018.html