题干:

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

解题报告:

看到数据量,猜到二分图。然后仔细分析二分图确实是可解的,正好二分图自带记录路径,,可能还是不是很熟练吧第一反应没有建模成二分图。左侧是行,右侧是列,然后跑二分图就可以了、题目没说求最短的变换次数,只是说一个specialjudge唯一要求是小于1000的变换次数。所以用二分图找到之后,那最多就是变换n次嘛(但是也有可能小于n次,比如第一个样例,就直接换了一次凑出俩来,严谨来讲(n/2)<=cnt<=n),n<=100,所以肯定满足题意啊。如果说求最少的变换次数,那就应该先把(ans[i]== j && ans[j] == i)的找出来,然后再遍历剩下的?(但是感觉好像和直接遍历的  次数差不多啊。。但是不太会证明、、)

AC代码:(140ms)

#include<bits/stdc++.h>using namespace std;
const int MAX = 100 + 5;
bool used[MAX];
int line[MAX][MAX],nxt[MAX],ans[MAX],n,cnt;
bool find(int x) {for(int i = 1; i<=n; i++) {if(line[x][i] && used[i] == 0) {used[i]=1;if(nxt[i] == 0 || find(nxt[i])) {nxt[i] = x;return 1;}}}return 0;
}
int main()
{while(~scanf("%d",&n)) {cnt = 0;memset(line,0,sizeof line);memset(ans,0,sizeof ans);memset(nxt,0,sizeof nxt);for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {scanf("%d",&line[i][j]);}}for(int i = 1; i<=n; i++) {memset(used,0,sizeof used);if(find(i)) cnt++;}if(cnt != n) {puts("-1");continue;}cnt = 0;for(int i = 1; i<=n; i++) {ans[nxt[i]] = i;//ans[i] = j   第i列应该等于第j列 //或者说 第i行换到第j行 }for(int i = 1; i<=n; i++) {if(ans[i] != i) {//如果这行需要换for(int j = i+1; j<=n; j++) {if(ans[j] == i) {swap(ans[i],ans[j]);cnt++;}}}}printf("%d\n",cnt);for(int i = 1; i<=n; i++) {ans[nxt[i]] = i;//ans[行] = 列 }for(int i = 1; i<=n; i++) {if(ans[i] != i) {for(int j = i+1; j<=n; j++) {if(ans[j] == i) {printf("R %d %d\n",i,j);swap(ans[i],ans[j]);}}}}} return 0 ;} 

总结:

for(int i = 1; i<=n; i++) {
            ans[nxt[i]] = i;//ans[行] = 列 
        }

这一行作用是:ans[i]=j,表示第i行应该换到第j行。(你如果最后输出是C的,也就是换列的,那就不需要这个转换了)

还有一点值得注意,我们的思路不是 如果第i行需要换(即ans[i]=j),则把i和j交换,并且用一个bk数组标记第j行已经完成,再从1找第一个bk=0的行,然后再进行交换。(这样会使代码写起来复杂。而且每次都得从i=1开始找,因为有可能ans[i]=j其中j<i?不知道会不会有这种可能性)(但是时间复杂度是不会变的,因为每次都会有一个行被确定下来)

当然,也可以AC,下面是部分代码:(140ms)

     for(int i = 1; i<=n; i++) {ans[nxt[i]] = i;//ans[行] = 列 }int flag = 0;while(1) {flag = 0;for(int i = 1; i<=n; i++) {if(ans[i] != i) {flag = 1;int j = ans[i];printf("R %d %d\n",i,j);swap(ans[i],ans[j]);break;}}            if(flag == 0) break;} 

但是,我们不妨换个思路,扫到这行i之后,然后现在我们的想法是要把这样固定下来,也就是,从后面的行中找到一行假设为j,使得ans[j] = i , 也就是用第j行来确定第i行,然后这两行交换,这样一个for循环扫每一行就可以了,扫到一行,就从后面的行中找一行来确定这一行。就ok了。至于为什么从i+1行开始,是因为第1~(i-1)行,都已经是ans[i]=i了呀,这也就是这两个方法的不同。(前者是找到一个可以更新别的行的行,然后去更新后面的行;后者是枚举每一行,然后从后面找一行来更新这一行。不过代码实现起来都是if(ans[i] != i)这一句)

*【HDU - 2819】Swap(二分图匹配,输出路径)(待证明:是否是最少交换次数?)相关推荐

  1. HDU - 2819 Swap(二分图完备匹配+路径输出)

    题目链接:点击查看 题目大意:给出一个n*n的01矩阵,问能否通过数次交换行和列,使得主对角线上的值全部为1 题目分析:因为对角线上的每个元素都对应着不同的一行和一列,换句话说,如果有解,那么肯定可以 ...

  2. HDU 2819 Swap(二分图匹配)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=2819 [题目大意] 给出一个棋盘,由白格子和黑格子组成,可以交换棋盘的行列, 使得其主对角线为黑格 ...

  3. 奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)

    题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.  这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百 ...

  4. Assignment HDU - 2853(二分图匹配 KM)

    传送门:QAQ 题意:给了你n个公司和m个任务,然后给你了每个公司处理每个任务的效率.然后他已经给你了每个公司的分配方案,让你求出最多能增大多少效率(即最大权值匹配减去原来的),然后问你至少要修改多少 ...

  5. HDU 1083 Coures(二分图匹配)

    解题思路: 裸的匈牙利算法,看最大匹配是否等于P: #include <iostream> #include <cstring> #include <cstdlib> ...

  6. URAL 1721 Two Sides of the Same Coin(二分图匹配,输出匹配对象)

    题意:给出n个人的信息,名字.特征.排名. 在排名相差2的前提下,特征为testdata可以与特征为statements的组队,特征为anything可以任何一人组队: 求最多匹配对数,并将每队名字输 ...

  7. HDU 2444 The Accomodation of Students 二分图匹配

    HDU 2444 The Accomodation of Students 二分图匹配 题目来源: HDU 题意: 给出学生数n和关系数m,接下来给出m个关系. 要求将学生分成两部分,每一部分不能有互 ...

  8. 【 HDU - 5093】Battle ships(匈牙利算法,二分图匹配)

    题干: Dear contestant, now you are an excellent navy commander, who is responsible of a tough mission ...

  9. hdu 4160 (Dolls)二分图的最小路径覆盖

    关于二分图,让人很头疼啊!归结为一句话,就是看不出来题目是二分图的问题. 也许是对二分图不太熟悉吧!需要多练习! 题目大意:给出n个箱子,每个箱子的参数为长,宽,高:(a,b,c):当且仅当箱子s1, ...

最新文章

  1. python实现加密字符串_Python实现对字符串的加密解密方法示例
  2. 预测 “疯狂三月” 冠军的办法,我只告诉你!
  3. jdk-12.0.2 64位最新版
  4. redux-form(V7.4.2)笔记(一)
  5. 关于ALV GRID的颜色
  6. JQuery进阶学习
  7. POJ-3067 Japan(树状数组、线段树)
  8. linux 小命令1
  9. 打车应用上马快递业务靠谱吗?
  10. PHP年龄计算 取得两个时间戳相差的年龄年月日显示
  11. 蓝桥杯 基础练习 数列特征
  12. oracle成本抛转,抛砖引玉:CBO成本计算初探
  13. 2018 年,新手前端是否真的很难找工作?
  14. java随机生成字母用三元运算符,【代码笔记】Java常识性基础补充(一)——赋值运算符、逻辑运算符、三元运算符、Scanner类、键盘输入、Random类、随机数...
  15. 《移动App测试的22条军规》—App测试综合案例分析23.11节测试微信App对多语言和地区的支持...
  16. 从程序员到项目经理:原来一切问题都是可以解决的
  17. C#笔记 使用自定义事件(含参)
  18. 格拉布斯准则异常数据_异常处理准则和最佳实践
  19. python语言磁力搜索引擎源码公开,基于DHT协议
  20. WinZip Pro 9 for Mac(专业zip压缩解压工具)

热门文章

  1. [BUGKU][CTF][PWN][2020] PWN writeup
  2. 力扣:组合总和 II DFS剪枝
  3. HDU-4282 A very hard mathematic problem 技巧枚举+二分
  4. HDU 6168 Numbers 思维
  5. jdk安装失败_windows配置安装单个Tomcat
  6. C#中宏定义#define、预处理#if #else #endif的使用
  7. go java性能_服务端I/O性能大比拼:Node、PHP、Java和Go
  8. java写一个web聊天工具_javaweb写的在线聊天应用
  9. python 局域网扫描_Python 简化版扫描局域网存活主机
  10. asterisk的NAT配置