hdu 2819 Swap(二分图匹配)

hdu 2819 Swap

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

题目大意:给你一个由0和1组成的矩阵,问能不能通过交换行和列来使这个矩阵中的G[i][i] = 1(对角线)。不能输出-1,能的话输出交换次数和交换策略。

解题思路:如果这个矩阵有一行或者一列全为零,则这个矩阵不可能达到目标状态。左边为1所在的坐标的行号,右边为1所在的坐标的列号,进行匹配,若求出的最大匹配等于n,则可以交换到目标状态。策略的话,根据匹配时的记录数组来找就行了(详细见代码)。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;

const int N = 1105;
typedef long long ll;
int n;
int G[N][N], R[N];
int a[N], b[N];
int vis[N];

bool input() {
    memset(R, 0, sizeof(R));
    memset(G, 0, sizeof(G));
    int a, flag, flag2 = 1;
    for (int i = 1; i <= n; i++) {
        flag = 0;
        for (int j = 1; j <= n; j++) {
            scanf("%d", &a);
            if (a) {
                flag = 1;
                G[i][j] = 1;
            }
        }
        if (!flag) flag2 = 0;
    }
    if (!flag2) {
        printf("-1\n");
        return false;
    }
    return true;
}
int find(int x) {
    for (int i = 1; i <= n; i++) {
        if (G[x][i] && !vis[i]) {
            vis[i] = 1;
            if (R[i] == 0 || find(R[i])) {
                R[i] = x;
                return 1;
            }
        }
    }
    return 0;
}

int hungary() {
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        memset(vis, 0, sizeof(vis));
        if (find(i)) ans++;
    }
    return ans;
}

void solve() {
    int ans = 0;
    int m;
    for (int i = 1; i <= n; i++) {
        m = i;
        for (int j = i; j <= n; j++) {
            if (R[j] <= R[m]) m = j;
        }
        if (m != i) {
            a[ans] = m, b[ans] = i;
            ans++;
            int temp = R[m];
            R[m] = R[i];
            R[i] = temp;
        }
    }
    printf("%d\n", ans);
    for (int i = 0; i < ans; i++) {
        printf("C %d %d\n", a[i], b[i]);
    }

}

int main() {
    while (scanf("%d", &n) != EOF) {
        if (!input()) continue;
        int ans = hungary();
        if (ans != n) {
            printf("-1\n");
            continue;
        }
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不可转载。

时间: 2024-10-04 01:41:00

hdu 2819 Swap(二分图匹配)的相关文章

E - Swap - hdu 2819(简单二分图匹配)

题意:如果可以交换行列,问主对角线能不能全为1 分析:要想主对角线全为1很明显要有N个行列不想同的点就行了,可以用二分图匹配计算出来多能有几个.如果小与N就不能.输出要是对的就行,不必和答案一样 ************************************************************************ #include<stdio.h>#include<algorithm>#include<string.h>using namesp

HDU 2819 — Swap 二分匹配

Swap Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2174    Accepted Submission(s): 774Special Judge Problem Description Given an N*N matrix with each entry equal to 0 or 1. You can swap any tw

HDU 2819 Swap (二分匹配+破输出)

题意:给定上一个01矩阵,让你变成一个对角全是 1 的矩阵. 析:二分匹配,把行和列看成两个集合,用匈牙利算法就可以解决,主要是在输出解,在比赛时一紧张不知道怎么输出了. 输出应该是要把 match[i] = i 这样的输出,然后再改掉后面那个,真是个大傻逼输出,气死了..... 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <strin

MZL&#39;s City (hdu 5352 最小费用流 ||二分图匹配)

MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 719    Accepted Submission(s): 251 Problem Description MZL is an active girl who has her own country. Her big country has N cities num

hdu 5727 Necklace 二分图匹配

题目链接 给2*n个珠子, n<=9, n个阴n个阳. 然后将它们弄成一个环, 阴阳交替.现在给你m个关系, 每个关系给出a, b. 如果阳a和阴b挨着, 那么a就会变暗. 问你最小变暗几个阳. 我们求出阴的所有全排列, 是9!, 因为形成一个环. 所以可以想象成一个珠子是固定不变的, 剩下n-1个变, 所以就是8!. 然后对于每种情况, 就是我们熟悉的二分图匹配了. 对于两个阴珠之间的空隙, 如果阳珠可以放到这里就连一条边. 然后跑匈牙利匹配就可以了. 9!过不了... #include <

A - Fire Net - hdu 1045(二分图匹配)

题意:一个阵地可以向四周扫射,求出来最多能修多少个阵地,墙不可以被扫射透,阵地不能同行或者或者列(有墙隔着例外) 分析:很久以前就做过这道题..当时是练习深搜来着,不过时间复杂度比较高,现在再看突然发现原来可以用二分图匹配来做,时间soso的 ****************************************************************** #include<stdio.h>#include<string.h>#include<algorit

HDU - 2819 Swap(二分匹配)

题意:交换任意两行或两列,使主对角线全为1. 分析: 1.主对角线都为1,可知最终,第一行与第一列匹配,第二行与第二列匹配,……. 2.根据初始给定的矩阵,若Aij = 1,则说明第i行与第j列匹配,据此求最大匹配数cnt,若cnt==N,才可通过交换使主对角线都为1. 3.交换时,可只交换行或只交换列.如:只交换列,行不变(顺序为1,2,3,……,n),那么对于列,只需要根据选择排序,将每行一开始匹配的列的顺序最终也变成1,2,3,……,n即可,因为是选择排序,每次选择第i小的交换到第i个位置

hdu 2819 Swap【完美二分匹配】

Swap Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2514    Accepted Submission(s): 900 Special Judge Problem Description Given an N*N matrix with each entry equal to 0 or 1. You can swap any

D - 棋盘游戏 - HDU 1281(二分图匹配)

分析:先求出来最大匹配数,然后用匹配的点一个一个去除看看能否达到最大匹配,能的话就是关键点(很暴力啊),不过竟然才31ms ***************************************************************** #include<stdio.h>#include<string.h>#include<algorithm>using namespace std; const int MAXN = 105; bool G[MAXN]