*【HDU - 2819】Swap(二分图匹配,输出路径)(待证明:是否是最少交换次数?)
题干:
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(二分图匹配,输出路径)(待证明:是否是最少交换次数?)相关推荐
- HDU - 2819 Swap(二分图完备匹配+路径输出)
题目链接:点击查看 题目大意:给出一个n*n的01矩阵,问能否通过数次交换行和列,使得主对角线上的值全部为1 题目分析:因为对角线上的每个元素都对应着不同的一行和一列,换句话说,如果有解,那么肯定可以 ...
- HDU 2819 Swap(二分图匹配)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=2819 [题目大意] 给出一个棋盘,由白格子和黑格子组成,可以交换棋盘的行列, 使得其主对角线为黑格 ...
- 奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)
题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百 ...
- Assignment HDU - 2853(二分图匹配 KM)
传送门:QAQ 题意:给了你n个公司和m个任务,然后给你了每个公司处理每个任务的效率.然后他已经给你了每个公司的分配方案,让你求出最多能增大多少效率(即最大权值匹配减去原来的),然后问你至少要修改多少 ...
- HDU 1083 Coures(二分图匹配)
解题思路: 裸的匈牙利算法,看最大匹配是否等于P: #include <iostream> #include <cstring> #include <cstdlib> ...
- URAL 1721 Two Sides of the Same Coin(二分图匹配,输出匹配对象)
题意:给出n个人的信息,名字.特征.排名. 在排名相差2的前提下,特征为testdata可以与特征为statements的组队,特征为anything可以任何一人组队: 求最多匹配对数,并将每队名字输 ...
- HDU 2444 The Accomodation of Students 二分图匹配
HDU 2444 The Accomodation of Students 二分图匹配 题目来源: HDU 题意: 给出学生数n和关系数m,接下来给出m个关系. 要求将学生分成两部分,每一部分不能有互 ...
- 【 HDU - 5093】Battle ships(匈牙利算法,二分图匹配)
题干: Dear contestant, now you are an excellent navy commander, who is responsible of a tough mission ...
- hdu 4160 (Dolls)二分图的最小路径覆盖
关于二分图,让人很头疼啊!归结为一句话,就是看不出来题目是二分图的问题. 也许是对二分图不太熟悉吧!需要多练习! 题目大意:给出n个箱子,每个箱子的参数为长,宽,高:(a,b,c):当且仅当箱子s1, ...
最新文章
- python实现加密字符串_Python实现对字符串的加密解密方法示例
- 预测 “疯狂三月” 冠军的办法,我只告诉你!
- jdk-12.0.2 64位最新版
- redux-form(V7.4.2)笔记(一)
- 关于ALV GRID的颜色
- JQuery进阶学习
- POJ-3067 Japan(树状数组、线段树)
- linux 小命令1
- 打车应用上马快递业务靠谱吗?
- PHP年龄计算 取得两个时间戳相差的年龄年月日显示
- 蓝桥杯 基础练习 数列特征
- oracle成本抛转,抛砖引玉:CBO成本计算初探
- 2018 年,新手前端是否真的很难找工作?
- java随机生成字母用三元运算符,【代码笔记】Java常识性基础补充(一)——赋值运算符、逻辑运算符、三元运算符、Scanner类、键盘输入、Random类、随机数...
- 《移动App测试的22条军规》—App测试综合案例分析23.11节测试微信App对多语言和地区的支持...
- 从程序员到项目经理:原来一切问题都是可以解决的
- C#笔记 使用自定义事件(含参)
- 格拉布斯准则异常数据_异常处理准则和最佳实践
- python语言磁力搜索引擎源码公开,基于DHT协议
- WinZip Pro 9 for Mac(专业zip压缩解压工具)
热门文章
- [BUGKU][CTF][PWN][2020] PWN writeup
- 力扣:组合总和 II DFS剪枝
- HDU-4282 A very hard mathematic problem 技巧枚举+二分
- HDU 6168 Numbers 思维
- jdk安装失败_windows配置安装单个Tomcat
- C#中宏定义#define、预处理#if #else #endif的使用
- go java性能_服务端I/O性能大比拼:Node、PHP、Java和Go
- java写一个web聊天工具_javaweb写的在线聊天应用
- python 局域网扫描_Python 简化版扫描局域网存活主机
- asterisk的NAT配置