hdu 2819 Swap
2014-03-11 12:45
351 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2819
题目大意:通过行列交换,让矩阵中主对角线的值全为1。
题目分析:只交换行或者只交换列都是可以换出来的,此题为二分图的匹配问题,x集合为行号,y集合为列号,用匈牙利算法完成匹配。
代码参考:
#include<map>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 200;
bool vis
;//记录y中节点是否使用
int cx
, cy
, g
, ansx
, ansy
;
int n;//二分图中x和y中点的数目
bool dfs(int u)// 匈牙利算法
{
for (int v = 1; v <= n; ++v)
{
if (g[u][v] && !vis[v])//如果节点v与u相邻并且未被查找过
{
vis[v] = true;//标记v为已查找过
if (cy[v] == -1 || dfs(cy[v]))//如果v未在前一个匹配cy中,或者v在匹配cy中,但是从与v相邻的节点出发可以有增广路径
{//记录查找成功记录,更新匹配cx,cy
cx[u] = v;
cy[v] = u;
return true;//返回查找成功
}
}
}
return false;// 不存在增广路,返回失败
}
int MaxMatch()
{
int res = 0;//找到多少匹配
//设置初始匹配
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
for (int i = 1; i <= n; ++i)
{
memset(vis, 0, sizeof(vis)); //清空上次搜索时的标记
if (dfs(i)) //从节点i尝试扩展
{
res++;//找到新的匹配
}
else
{
break;
}
}
return res;
}
int main()
{
int m, t, i, j, k;
while (~scanf("%d", &n))
{ //构造二部图
for (i = 1; i <= n; ++i)
{
for (j = 1; j <= n; ++j)
{
scanf("%d", &g[i][j]);//记录连接x和y的边,如果i和j之间有边则为1,否则为0
}
}
if (MaxMatch() != n)
{
puts("-1");
continue;
}
int len = 0;
for (i = 1; i <= n; ++i)//选择排序
{
int p = i;
for (j = i; j <= n; ++j)
{
if (cy[p] > cy[j])//列对应的行从小到大排序
{
p = j;
}
}
if (p == i)
{
continue;
}
//交换的列,就是要输出的
ansx[++len] = i;
ansy[len] = p;
swap(cy[p], cy[i]);
}
printf("%d\n", len);
for (i = 1; i <= len; ++i)
{
printf("C %d %d\n", ansx[i], ansy[i]);
}
}
return 0;
}
题目大意:通过行列交换,让矩阵中主对角线的值全为1。
题目分析:只交换行或者只交换列都是可以换出来的,此题为二分图的匹配问题,x集合为行号,y集合为列号,用匈牙利算法完成匹配。
代码参考:
#include<map>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 200;
bool vis
;//记录y中节点是否使用
int cx
, cy
, g
, ansx
, ansy
;
int n;//二分图中x和y中点的数目
bool dfs(int u)// 匈牙利算法
{
for (int v = 1; v <= n; ++v)
{
if (g[u][v] && !vis[v])//如果节点v与u相邻并且未被查找过
{
vis[v] = true;//标记v为已查找过
if (cy[v] == -1 || dfs(cy[v]))//如果v未在前一个匹配cy中,或者v在匹配cy中,但是从与v相邻的节点出发可以有增广路径
{//记录查找成功记录,更新匹配cx,cy
cx[u] = v;
cy[v] = u;
return true;//返回查找成功
}
}
}
return false;// 不存在增广路,返回失败
}
int MaxMatch()
{
int res = 0;//找到多少匹配
//设置初始匹配
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
for (int i = 1; i <= n; ++i)
{
memset(vis, 0, sizeof(vis)); //清空上次搜索时的标记
if (dfs(i)) //从节点i尝试扩展
{
res++;//找到新的匹配
}
else
{
break;
}
}
return res;
}
int main()
{
int m, t, i, j, k;
while (~scanf("%d", &n))
{ //构造二部图
for (i = 1; i <= n; ++i)
{
for (j = 1; j <= n; ++j)
{
scanf("%d", &g[i][j]);//记录连接x和y的边,如果i和j之间有边则为1,否则为0
}
}
if (MaxMatch() != n)
{
puts("-1");
continue;
}
int len = 0;
for (i = 1; i <= n; ++i)//选择排序
{
int p = i;
for (j = i; j <= n; ++j)
{
if (cy[p] > cy[j])//列对应的行从小到大排序
{
p = j;
}
}
if (p == i)
{
continue;
}
//交换的列,就是要输出的
ansx[++len] = i;
ansy[len] = p;
swap(cy[p], cy[i]);
}
printf("%d\n", len);
for (i = 1; i <= len; ++i)
{
printf("C %d %d\n", ansx[i], ansy[i]);
}
}
return 0;
}
相关文章推荐
- HDU 2819 Swap 二分匹配
- HDU 2819 Swap (行列匹配+输出解)
- hdu 2819 Swap【完美二分匹配】
- HDU 2819 Swap (二分图-行列匹配+输出解)
- hdu 2819 Swap(二分图匹配)
- hdu2819 Swap
- hdu 2819 Swap(二分图匹配)
- HDU - 2819 Swap (二分匹配+输出路径)
- HDU 2819 Swap 最大匹配问题
- hdu 2819 Swap
- HDU-2819 Swap
- HDU 2819 — Swap 二分匹配
- hdu2819 Swap
- hdu 2819 Swap(二分匹配+记录路径,好题)
- hdu 2819 Swap
- hdu 2819 Swap
- HDU 2819 Swap 【二分图匹配 交换方法】
- Swap——hdu 2819
- hdu 2819 Swap
- HDU 2819 Swap【二分图|启发题】