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?
Source: Multi-School Training Contest - TOJ Site #1
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), separated by space, indicating the N * N matrix.
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 not be more than 1000.
If it is impossible to make all the diagonal entries equal to 1, output only one one containing "-1".
2 0 1 1 0 2 1 0 1 0
1 R 1 2 -1
Author:HE, Liang
Note: Special judge problem, you may get "Wrong Answer" when output in wrong format.
这道题出的很好,的确。
刚开始我一直在思考,到底能不能用匹配做他。因为我在想是否交换两行会导致无效的转换。
后来想了想,这道题目,其实只是为了让我们去找N个不同行不同列的1,所以我们在交换行或列的时候不会影响到已经在对角线上的元素了(这一点我还是有一些疑惑,我加了一些保证他不改变对角线上元素的判断语句,但都WA,也不知道为什么)
另外就是输出交换的语句的时候,集中在要么行交换,要么列交换,在这二者中选一个就可以了。
#include<stdio.h>
#include<string.h>
int n;
int map[101][101],link[101];
bool mat[101][101],used[101];
int change[101][2];
bool can(int t)
{
for(int i=1;i<=n;i++)
if(used[i]==false&&mat[t][i])
{
used[i]=true;
if(link[i]==-1||can(link[i]))
{
link[i]=t;
return true;
}
}
return false;
}
int MaxMatch()
{
memset(link,-1,sizeof(link));
for(int i=1;i<=n;i++)
{
memset(used,false,sizeof(used));
if(!can(i)) return false;
}
return true;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int cas=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==1) mat[i][j]=true,cas++;
else mat[i][j]=false;
}
//if(cas==n*n) printf("0/n");
//else
if(cas<n||!MaxMatch()) printf("-1/n");
else
{
int cnt=0;
//printf("%d %d/n",link[1],link[2]);
for(int i=1;i<=n;i++)//对行进行匹配
{
if(link[i]==i) continue;//这个列上的元素已经在对角线上,对角线:I==J
int j;
for(j=1;j<=n;j++)
{
if(link[j]==i) break;
}
int temp=link[i];
link[i]=link[j];
link[j]=temp;
change[++cnt][0]=i;
change[cnt][1]=j;
}
printf("%d/n",cnt);
for(int i=1;i<=cnt;i++)
printf("C %d %d/n",change[i][0],change[i][1]);
}
}
return 0;
}