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
给一个矩阵,判断是否能通过交换行或者列,使这个矩阵的对角线(主对角线)上的元素都为1。如果能,那么给出交换的顺序。
这个题最开始我是想用线性代数来解,化成单位阵,判断矩阵有没有逆不就完事了。但是算行列式数据给的太大了,然后,就没有然后了。
之后,根据题意,在对角线位置上换个一出来1出来,那就先找到这一列中那几行有1,答案必定在几行里。如果将每一行和列都抽象成一个点,那么不久成了一个二分图匹配的问题了么。
综上,现在对矩阵的判断转换成了求二分图的最大匹配,根据最大匹配数来判断是否能构成单位阵。如果能,再考虑交换顺序的给出。
根据线性代数中的知识,一个初等阵一定可以仅通过行变换或者仅通过列变换化为初等阵。所以在交换时,可以只考虑交换行或者交换列,在这里以交换行为例。
运行匈牙利算法之后,可以在match数组中找到匹配关系,也就是 对于第 i 列选择第 match[i] 行交换到第 i 行。注意的是,match[i]中行的序号始终是对原矩阵而言,不随交换而发生变化。比如第1行要与 match[1]:4 行交换,这样现在的第1行就是原矩阵的第4行,原矩阵的第1行现在位于第4行;之后第2行要与 match[2]:1 行交换,这里的第1行是原矩阵的第1行,就是现矩阵的第4行。
所以要建立一个映射关系:原矩阵的第 i 行位于现矩阵的第 pos[i] 行,并在交换的时候正确的修正这个映射。
#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>
#define colStar 105
#define MAXN 210
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
bool used[MAXN];
int match[MAXN];
int pos[MAXN];
int store[105][105];
vector<int> adj[MAXN];
bool dfs(int v);
int main(){
ios::sync_with_stdio(false);
int n;
while(cin>>n){
rep(i,1,n+1){
rep(j,1,n+1)
cin>>store[i][j];
}
//recode
rep(i,1,n+1){
rep(j,1,n+1){
if(store[j][i]){
adj[colStar+i].Push(j);
}
}
}
int peak=0;
memset(match,-1,sizeof(match));
rep(i,1,n+1){
int v=i+colStar;
if(adj[v].size()>0 && match[v]<0){
memset(used,false,sizeof(used));
if(dfs(v))
peak++;
}
}
if(peak==n){
cout<<peak<<endl;
rep(i,1,n+1)
pos[i]=i;
rep(i,1,n+1){
int v=i+colStar;
if(match[v]<0)
continue;
else{
cout<<"R "<<pos[match[v]]<<" "<<i<<endl;
rep(x,1,n+1)
if(i==pos[x]){
pos[x]=pos[match[v]];
break;
}
pos[match[v]]=i;
}
}
}else
cout<<"-1"<<endl;
rep(i,0,MAXN)
adj[i].erase(adj[i].begin(),adj[i].end());
}
re 0;
}
bool dfs(int v){
used[v]=true;
rep(i,0,adj[v].size()){
int u=adj[v][i],matched=match[u];
if(matched<0 || !used[matched] && dfs(matched)){
match[v]=u;
match[u]=v;
return true;
}
}
return false;
}
给几组数据
2
0 1
1 0
1
0
4
0 1 0 1
1 1 0 1
1 0 1 0
0 1 1 0
4
1 1 0 0
1 0 1 0
1 0 0 1
1 0 0 0