「HDU2819」 Swap 题解

问题

原题链接 HDU2819

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

Input
1
2
3
4
5
6
2  
0 1
1 0
2
1 0
1 0

Sample Output

Output
1
2
3
1  
R 1 2
-1

题目大意

给定 N×NN \times N 的矩阵,矩阵中每一个位置都有 11 个数 00 或者 11 ,现在需要你通过交换某两行或者某两列使得这个矩阵的对角线的格子中都是 11 ,如果有解则输出任意一组解,如果没有解则输出 1-1

1N1001 \leq N \leq 100

其中输入数据包含若干组数据,每组数据第一行为 nn ,接下来 NN 行 每行包括 NN 个数代表这个矩阵。

对于每组数据,如果有解,则第一行输出交换的次数 kk ,接下来 kk 行第一个为 RR 或者 CC 表示交换行或者列,第二三个数据 iijj 表示交换第 ii 与第 jj 行或列。

解题

不难发现,如果每一行都能找到一个与其他行不冲突的列,并且行与列的交点位置为 11 ,则可以通过交换行或列使得对角线上都为 11

对于每一个位置 (i,j)(i, j) ,如果这个位置的数为 11 ,则从 ii 号点向 jj 号点连边,表示 ii 行与 jj 列可以进行匹配,建图完成后,对这个二分图进行匹配,如果能形成 NN 个匹配则说明每一行都能找到与其他行不冲突的一列,并且交点位置是 11 ,即有解,否则无解。

最后在根据 result 数组统计输出方案即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100 + 5;
bool mp[MAXN][MAXN];
int use[MAXN], ut;
int result[MAXN];
int repi[MAXN];
int repj[MAXN];
int n;
bool dfs(int i) {
for(int j = 1; j <= n; j++) {
if(use[j] != ut && mp[j][i]) {
use[j] = ut;
if(!result[j] || dfs(result[j])) {
result[j] = i;
return true;
}
}
}
return false;
}
int xiongyali() {
memset(result, 0, sizeof(result));
int ans = 0;
for(int i = 1; i <= n; i++) {
ut++;
if(dfs(i)) ans++;
}
return ans;
}
int main() {
while(cin >> n) {
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
cin >> mp[i][j];
}
}
int res = xiongyali();
if(res == n) {
int cnt = 0;
for(int i = 1; i <= n; i++) {
if(result[i] != i)
for(int j = i + 1; j <= n; j++) {
if(result[j] == i) {
cnt++;
repi[cnt] = i;
repj[cnt] = j;
result[j] = result[i];
result[i] = i;
break;
}
}
}
cout << cnt << endl;
for(int i = 1; i <= cnt; i++) {
cout << "R " << repi[i] << ' ' << repj[i] << endl;
}
}
else cout << "-1" << endl;
}
return 0;
}