Matrix Transformer zoj3646 (二分图最大匹配)

19 篇文章 0 订阅
2 篇文章 0 订阅

Description

Alice and Bob meet again. This time they play a game named MATRIX TRANSFORMER.

They got an n * n board. Every grid has two positions, UP and DOWN. In this game you can push some amazing buttons to exchange any two rows or any two columns. Alice will win if she got the grids in the main diagonal line all UP.

But Alice finds that for some board, no matter how many times she tries, she cannot get the grids in the main diagonal line all UP. Now she asks you for help, tell her if she can win this board or not.

Input

There are several test cases. 
For each test case: 
The 1st line contains 1 integer n, indicating the size of the board. (1 ≤ n ≤ 200) 
The next n lines, each contains n characters. 'U' indicates the position UP, and 'D' indicates the position DOWN. 
There is no separation line between any two test cases.

Output

For each test case, you should print one line. You should print 'YES' if Alice can win, print 'NO' if not. 

Sample Input

3
DUD
UDD
DDU
3
DUD
DUD
UDD

Sample Output

YES
NO

思路:能够将主对角线全部变成U至少需要有n个不同行不同列的U,因此考虑构建二分图,若存在 s[i][j]=='U' 则添加一条边 <i,j>,然后再做一次二分图匹配,最大匹配值为n则证明至少存在n个不同行不同列的U,否则不存在。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
const long M=210;
long head[M],to[M*M],Next[M*M],cnt;
long link[M],vis[M],n;

void init_edge(){
	memset(head,-1,sizeof(head));
	memset(link,0,sizeof(link));
	cnt=0;
}
void add_edge(long u,long v){
	Next[cnt]=head[u]; to[cnt]=v; head[u]=cnt++;
}

long dfs(long u){
	for (long i=head[u];i!=-1;i=Next[i]){
		long v=to[i];
		if (vis[v]) continue;  vis[v]=1;
		if (!link[v] || dfs(link[v])){
			link[v]=u;
			return 1;
		}
	}
	return  0;
}

int main(){
	while (~scanf("%d",&n)){
		init_edge();
		for (long i=1;i<=n;++i){
			char c;  getchar();
			for (long j=1;j<=n;++j){
				scanf("%c",&c);
				if (c=='U') add_edge(i,j);
			}
		}

		long ans=0;
		for (long i=1;i<=n;++i){
			memset(vis,0,sizeof(vis));
			if (dfs(i)) ans++;
		}
		if (ans==n) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值