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; }