zoukankan      html  css  js  c++  java
  • hdu-2819.swap(二分匹配 + 矩阵的秩基本定理)

    Swap

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5728    Accepted Submission(s): 2157
    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
     
    Source
     
    Recommend
    gaojie

    这个题一开始没有想到是二分匹配,主要是不知道这个定理.

    矩阵的秩:

      一般矩阵经过初等变换之后得到的阶梯矩阵中,不全为0的行数为行秩,不全为0的列的个数为列秩,一个矩阵的行秩等于列秩等于矩阵的秩.

    矩阵的秩的一般定理:

      初等变换不能改变矩阵的秩.

     1 /*************************************************************************
     2     > File Name: hdu-2819.swap.cpp
     3     > Author: CruelKing
     4     > Mail: 2016586625@qq.com 
     5     > Created Time: 2019年09月02日 星期一 17时56分18秒
     6     本题大意:给定一个n × n 的0 or 1矩阵,问你若只交换某些行和列(行之间进行交换,列之间进行交换)能否使得最后的矩阵在从左上角到右下角的对角线上元素都为1.
     7     本题思路:线性代数里我们学过初等变换不会改变矩阵的秩,因此如果一个矩阵满秩,那么必定有解,如何判断矩阵是否满秩呢?因为是0 or 1矩阵,因此,原矩阵经过变换后得到的阶梯矩阵也都只有0 or 1,如果其中某两列的元素完全相等,或者某一列中本来就不存在1那么转换之后的阶梯矩阵自然也就不会满秩。所以我们可以对行和列缩点,判断是否每一列都有独特的一行与之对应,如果说有两列的1都存在与同一行,那么必定无法匹配,所以我们就想到了二分匹配,让行缩点为x,列缩点为y,匹配之后,如果最大匹配为n那么匹配成功,否则说明矩阵非满秩,如何输出解呢?我们遍历所有列,如果发现有一列与他匹配的行不与他的标号相等,则说明这个(i, j)位于第i行第j列,那么我们把第j列换到第i列即可.也就是交换j与linker[j],交换了之后肯定要改变其匹配状态,也就是让匹配i的行和匹配j的行再互换。
     8  ************************************************************************/
     9 
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <algorithm>
    13 using namespace std;
    14 
    15 const int maxn = 100 + 5, maxm = 1000 + 5, inf = 0x3f3f3f3f;
    16 
    17 typedef pair<int, int> pii;
    18 int n, linker[maxn], g[maxn][maxn];
    19 bool used[maxn];
    20 pii path[maxm];
    21 int tot;
    22 
    23 bool dfs(int u) {
    24     for(int v = 1; v <= n; v ++) {
    25         if(!used[v] && g[u][v]) {
    26             used[v] = true;
    27             if(linker[v] == -1 || dfs(linker[v])) {
    28                 linker[v] = u;
    29                 return true;
    30             }
    31         }
    32     }
    33     return false;
    34 }
    35 
    36 int main() {
    37     while(~scanf("%d", &n)) {
    38         tot = 0;
    39         for(int i = 1; i <= n; i ++) {
    40             for(int j = 1; j <= n; j ++) {
    41                 scanf("%d", &g[i][j]);
    42             }
    43         }
    44         memset(linker, -1, sizeof linker);
    45         int res = 0;
    46         for(int i = 1; i <= n; i ++) {
    47             memset(used, false, sizeof used);
    48             if(dfs(i)) res ++;
    49         }
    50         if(res != n) printf("%d
    ", -1);
    51         else {
    52             for(int i = 1; i <= n; i ++) {
    53                 while(i != linker[i]) {
    54                     path[tot ++] = make_pair(i, linker[i]);
    55                     swap(linker[i], linker[linker[i]]);
    56                 }
    57             }
    58             printf("%d
    ", tot);
    59             for(int i = 0; i < tot; i ++) {
    60                 printf("C %d %d
    ", path[i].first, path[i].second);
    61             }
    62         }
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    es6学习笔记--let和const
    最新数组方法(包括es6)
    es6学习笔记--模板字符串
    版本控制工具--svn和git的使用(三) -----git的使用(2)
    版本控制工具--svn和git的使用(三) -----git的使用(1)
    版本控制工具--svn和git的使用(二) -----SVN的操作
    版本控制工具--svn和git的使用(一) -----版本控制的好处以及分类
    e.preventDefault()和e.stopPropagation()以及return false的作用和区别
    Mybatis之SessionFactory原理
    Mybatis架构简介
  • 原文地址:https://www.cnblogs.com/bianjunting/p/11449162.html
Copyright © 2011-2022 走看看