您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2009 Multi-Universit