Problem Description
Given an N*N matrix with each entry equal to 0 or 1. You can swap any two rows or any two columns. Can you find a way to make all the diagonal entries equal to 1?
Input
There are several test cases in the input. The first line of each test case is an integer N (1 <= N <= 100). Then N lines follow, each contains N numbers (0 or 1), separating by space, indicating the N*N matrix.
Output
For each test case, the first line contain the number of swaps M. Then M lines follow, whose format is “R a b” or “C a b”, indicating swapping the row a and row b, or swapping the column a and column b. (1 <= a, b <= N). Any correct answer will be accepted, but M should be more than 1000.
If it is impossible to make all the diagonal entries equal to 1, output only one one containing “-1”.
Sample Input
2
0 1
1 0
2
1 0
1 0
Sample Output
1
R 1 2
-1
题目问是否能通过交换行列,使得01矩阵对角线上的所有元素都为1。
因为我们只关注对角线上的值,很容易想到交换列的结果能通过交换行来实现,交换行的结果也能通过交换列来实现。下面以交换行为例。
首先我们先判断是否每一列上都有1,如果不能保证这一条件,则无论如何交换行都无法实现,同时进行匹配过程,得到每一列所在行的位置。
为什么要用二分图匹配去求呢?假设maps[1][1] == 1,maps[1][2] == 1,但是这只能满足一行的条件,那么我们这时选第一行匹配了第一列还是第二列呢?这得看其他行的情况。假设maps[2][1] == 0,maps[2][2] == 1,那么第二行只能匹配第二列,此时第一行就要匹配第一列。这个过程就是二分图匹配的过程。
然后就可以进行暴力遍历,找每一行对应的点的匹配的值是否与其相同,如果不相同,则去寻找与其相同的点,用交换他们的匹配值来代表交换了行。
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
#define N 510
int vis[N], used[N], maps[N][N], n, ans;
vector<pair<int,int>>G;
bool Find(int u){
for(int i=1; i<=n; i++){
if(!vis[i] && maps[i][u]){
//因为读的时候读的是行与列的关系,所以这里遍历数组的第一维来找列与行的关系
vis[i] = 1;
if(!used[i] || Find(used[i])){
used[i] = u;
return true;
}
}
}
return false;
}
int main(){
int a, b, m, t;
while(~scanf("%d", &n)){
memset(maps, 0, sizeof(maps));
for(int i=1; i<=n; ++i)
for(int j=1;j<=n; ++j)
scanf("%d", &maps[i][j]);
ans = 0;
memset(used, 0, sizeof(used));
for(int i=1; i<=n; i++){
memset(vis, 0, sizeof(vis));
if(Find(i))
ans++;
}
if(ans != n){
puts("-1");
continue;
}
G.clear();
int num=0;
for(int i=1;i<=n;++i){
if(used[i] != i){
num++;
for(int j=i + 1;j<=n;++j){
if(used[j] == i){
G.push_back({i,j});//记录交换情况
swap(used[j],used[i]);
break;
}
}
}
}
printf("%d\n",num);
for(int i=0;i<num;++i){
printf("R %d %d\n",G[i].first,G[i].second);
}
}
return 0;
}