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

2009 Multi-University Training Contest 1 - Host by TJU

题目大意:给你一个 n*n的 矩阵,使用行交换或者列交换的方式来使得矩阵的主对角线(左上到右下)都是1.

分析:对于这个题,不需要最少的操作次数,那么我们无论是怎样做,只要是搞定了这个问题,我们就胜利了,对于输出-1的情况,我们来行列匹配看看能否使得所有行都有列来匹配就好,如果没有,那么就不是完美匹配,也就是说输出-1,否则就一定有结果输出。

思路:

完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。图
4 是一个完美匹配。显然,完美匹配一定是最大匹配(完美匹配的任何一个点都已经匹配,添加一条新的匹配边一定会与已有的匹配边冲突)。但并非每个图都存在完美匹配。

遍历所有行,如果都有列匹配的话,就是一个完美匹配,否则输出-1.

如果是完美匹配,那么交换pri【】数组,使得pri【i】=i、

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 505;
int map[maxn][maxn];              //图的数组.
int vis[maxn];                  //标记数组.
int pri[maxn];
int ans[maxn*2][2];
int n;
int  find(int x)
{
    for(int i=1; i<=n; i++)
    {
        if(vis[i]==0&&map[i][x])
        {
            vis[i]=1;
            if(pri[i]==-1||find(pri[i]))
            {
                pri[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    while(~scanf("%d",&n))
    {
        memset(pri,-1,sizeof(pri));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%d",&map[i][j]);
            }
        }
        int ok=1;
        for(int i=1; i<=n; i++)
        {
            memset(vis,0,sizeof(vis));
            if(find(i))continue;
            else ok=0;
        }
        if(ok==0){printf("-1\n");continue;}
        int cont=0;
        for(int i=1;i<=n;i++)
        {
            if(pri[i]==i)continue;
            for(int j=1;j<=n;j++)
            {
                if(pri[j]==i)
                {
                    swap(pri[i],pri[j]);
                    ans[cont][0]=i;ans[cont++][1]=j;
                }
            }
        }
        printf("%d\n",cont);
        for(int i=0;i<cont;i++)
        {
            printf("R %d %d\n",ans[i][0],ans[i][1]);
        }

    }
}
时间: 2024-10-07 09:09:12

hdu 2819 Swap【完美二分匹配】的相关文章

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(二分图匹配)

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 li

hdu 4185 Oil Skimming(二分匹配)

Oil Skimming Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 883    Accepted Submission(s): 374 Problem Description Thanks to a certain "green" resources company, there is a new profitable

HDU 1281 棋盘游戏(二分匹配 与 删边)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 根据题目描述,什么是重要点?在求出最大匹配后,进行枚举,依次删边,看最大匹配数会不会发生改变,改变的话,那么该点就是重要点. #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <

HDU 2119 Matrix 简单二分匹配

行做x集,列做y集,1就给该行该列连一条边,输出最大匹配边即可 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<set> using namespace std; #define N 105 int lef[N], pn;//lef[v]表示Y集的点v 当前连接的点 , pn为x点集的

HDU 1083 裸的二分匹配

Courses Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3424    Accepted Submission(s): 1650 Problem Description Consider a group of N students and P courses. Each student visits zero, one or

hdu 1054 Strategic Game (二分匹配)

Strategic Game Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4697    Accepted Submission(s): 2125 Problem Description Bob enjoys playing computer games, especially strategic games, but somet

hdu 1281 棋盘游戏 (二分匹配)

//是象棋里的车 符合二分匹配 # include<stdio.h> # include<algorithm> # include<string.h> using namespace std; int n,m,pp[110][110],map[110],vis[110]; int bfs(int x) { for(int i=1;i<=m;i++) { if(!vis[i]&&pp[x][i]) { vis[i]=1; if(!map[i]||bf

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

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

hdu 1281 棋盘游戏(二分匹配)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2905    Accepted Submission(s): 1702 Problem Description 小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽