Swap
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4467 Accepted Submission(s): 1664
Special Judge
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”.
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
Source
这道题的提议大致就是给你个矩阵,问你能不能移动这个矩阵的行或列使得矩阵的主对角线元素都为1,如果可以输出m移动次数,以及移动的是哪几行或那几列。
这道题当时卡了很久,然后在网上搜的题解,然后又自己理解理解,用了一天时间才把这道题搞明白。如果能使主对角线的元素全为1,说明更新完原有x和y的匹配关系过后新生成的匹配个数恰好为n。意思就是求这组数据的最大匹配并且最大匹配为N,才能符合题意。其余部分我将结合代码一起讲解。
#include<bits/stdc++.h>
using namespace std;
int e[101][101];
int match[1001],vis[1001];
int a[1001],b[1001];//a,b用来记录交换的行数/列数
int n;
bool dfs(int u){
int i;
for(i=1;i<=n;i++){
if(!vis[i]&&e[u][i]){
vis[i]=1;//标记该点已经访问过
if(!match[i]||dfs(match[i])){
match[i]=u;//更新配对关系
return 1;
}
}
}
return 0;
}
int main(){
while(~scanf("%d",&n)){
memset(e,0,sizeof(e));
memset(match,0,sizeof(match));//用来记录匹配关系
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&e[i][j]);
}
}
int ans=0,k=0;
//要是重构完匹配关系后使主对角线的元素都为1则最大匹配为n
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
/*printf("最大匹配关系\n");
for(int i=1;i<=n;i++){
printf("%d %d\n",i,match[i]);可以自己先输出一下更新后的匹配关系在去找要移动的行或者列
}*/
if(ans<n){
printf("-1\n");
}
else{
for(int i=1;i<=n;i++){
//查找最大匹配关系,然后移动对应的行/列
if(match[i]){
while(match[i]!=i){
a[k]=i;//储存其对应的行数
b[k]=match[i];//记录要交换的列
swap(match[a[k]],match[b[k]]);//交换列数
k++;
/*因为主对角线的元素全为1所以x==y,假设x1,y4
是更新完匹配关系后的匹配,但要是x==y,因为y4==x4,
所以就去找x4对应的列数和x1对应的列数y4交换上的x4==y4*/
}
}
}
printf("%d\n",k);
for(int i=0;i<k;i++){
printf("C %d %d\n",a[i],b[i]);
}
}
}
return 0;
}