hdu 2819 Swap

Swap

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1089    Accepted Submission(s): 366
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”. 
 
Sample Input
2 0 1 1 0 2 1 0 1 0
 
Sample Output
1 R 1 2 -1
 

 恶心的题

/*
这题要注意几个地方;
这题可用二分匹配来做(ps:看别人题解才知道可以这么做)
首先它是求等最大匹配
然后就是如果这题有解,我们可以
只通过交换行或者只通过交换列来达到要求(special judge)
以行为一个集合,以含1的列为一个集合,用匈牙利算法进行匹配就行了
匹配数量如果小于n就无解,否者记录路径,输出结果
*/
#include<stdio.h>
#include<string.h>
using namespace std;
int map[105][105];
int linky[105],vis[105];
int n,a[105],b[105];
int dfs(int x)
{
     int i;
     for(i=1;i<=n;i++)
     {
          if(map[x][i]&&!vis[i])
          {
               vis[i]=1;
               if(linky[i]==-1||dfs(linky[i]))
               {
                    linky[i]=x;
                    return 1;
               }
          }
     }
     return 0;
}
int main()
{
     int i,j,t;
     while(scanf("%d",&n)!=EOF)
     {
          for(i=1;i<=n;i++)
               for(j=1;j<=n;j++)
                 scanf("%d",&map[i][j]);
          memset(linky,-1,sizeof(linky));
          int ans=0;
          for(i=1;i<=n;i++)
          {
               memset(vis,0,sizeof(vis));
               if(dfs(i))
                    ans++;
          }
          if(ans<n)
          {
               printf("-1
");
               continue;
          }
          int k=0;
          for(i=1;i<n;i++)//i代表的是列,目的是要使得第i列的第i个元素为1
          {
               if(linky[i]!=i)//因为最终的目的是要使所有主对角线上的元素全为1,linky[i]记录的是匹配的行号
               {                     //如果linky[i]和列号相等就说明该行的第i个元素为1了,否者继续往后找
                    for(j=i+1;j<=n;j++)
                    {
                         if(linky[j]==i)//行号和列号相等就找到了
                         {
                              a[k]=i;//a,b数组记录交换次序
                              b[k++]=j;
                              t=linky[i];//这里交换的是列
                              linky[i]=linky[j];
                              linky[j]=t;
                         }
                    }
               }
          }
          printf("%d
",k);
          for(i=0;i<k;i++)
               printf("C %d %d
",a[i],b[i]);
     }
     return 0;
}
原文地址:https://www.cnblogs.com/llei1573/p/3272710.html