您的位置:首页 > 其它

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

2015-05-17 01:07 435 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: