HDU-2819

Swap

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1800    Accepted Submission(s): 606
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

Recommend

gaojie

/**
          题意:给出一个n*n的矩阵,然后进行行列变换,使得矩形的对角线上都是1
          做法:二分图匹配匈牙利
**/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
#define maxn 110
int g[maxn][maxn];
int linker[maxn];
bool vis[maxn];
vector<int>G[maxn];
int n;
int dfs(int u)
{
          for(int i=0;i<(int)G[u].size();i++)
          {
                    int v = G[u][i];
                    if(!vis[v])
                    {
                              vis[v] = true;
                              if(linker[v] == -1 || dfs(linker[v]))
                              {
                                        linker[v] = u;
                                        return 1;
                              }
                    }
          }
          return 0;
}
int hungary()
{
          int res  =0;
          memset(linker,-1,sizeof(linker));
          for(int i=0;i<n;i++)
          {
                    memset(vis,false,sizeof(vis));
                    res += dfs(i);
          }
          return res;
}
int main()
{
#ifndef ONLINE_JUDGE
          freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
          while(~scanf("%d",&n))
          {
                 for (int i = 0; i <= n; i++) G[i].clear();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                scanf("%d", &g[i][j]);
                if (g[i][j]) G[i].push_back(j);
            }
        }
                   int res = hungary();
                    if(res == n)
                    {
                              printf("%d\n",res);
                              for(int i=0;i<n;i++)
                              {
                                        printf("R %d %d\n",linker[i]+1,i+1);
                                        for(int j=0;j<n;j++)
                                        {
                                                  if(linker[j] == i ) linker[j] = linker[i];
                                        }
                              }
                    }
                    else printf("-1\n");
          }
          return 0;
}
时间: 2024-10-11 17:39:42

HDU-2819的相关文章

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 2819 隐式二分图匹配

http://acm.hdu.edu.cn/showproblem.php?pid=2819 这道题乍一看是矩阵变换题,估计用矩阵之类的也可以做 但是分析一下就可以知道 要凑成对角线都是1,题目允许行变换和列变换 然而观察可以得知如果可以完成只需要行变换或者列变换之一即可 donser[i][j]=1表示i,j位置有1,那么只需要变换j到i(即交换i,j行) 输出中间过程用queue 加上dfs遍历即可 #include<iostream> #include<cstdio> #in

hdu 2819 记录路径的二分匹配

题目大意就是给出一个矩阵,每个格子里面要么是0, 要么是1:是否能够经过交换(交换行或者列)使得主对角线上都是1. 其实就行和列的匹配,左边是行,右边是列,然后如果行列交点是1,那么就可以匹配,看是否为完美匹配,然后输出怎么交换的.开始很蒙的,后来仔细去 想,可以这样理解,想要对角线上都是1,那么我们就可以锁定行,来选择列和它匹配,将选择的列移动到和该行形成对角线上是1的位置,比如和第一行匹配的 列,就要移动要第一列,第二行的,就到第二列.其实就是对第i行,找一个第i个数是1的列和它匹配,然后看

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

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

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

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

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

专题之匹配、网络流(一)

1.hdu 2444 The Accomodation of Students(判断二分图+最大匹配)(匈牙利模板) 题意:一共有n个学生,m对关系:A认识B.问能否将所有的人分成两批,每批之间的人都互相认识,如果可以,输出每批的人数.即判断是否为二分图,以及求二分图的最大匹配. 思路:判断是否为二分图(DFS或BFS):求二分图的最大匹配:匈牙利算法. 1 #include<iostream> 2 #include<queue> 3 using namespace std; 4

kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图. 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知道什么是最小点覆盖,我也在这里说一下:假如选