HDU 2819 Swap(二分图匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=2819
题意:
给定一个矩阵,矩阵元素取值为0或1,每次操作可以交换任意两行或两列,要求对于给定矩阵给出操作次数和操作序列将主对角线(A[i][i],i=1...n)元素全部变为1,无法满足则输出-1.
分析:
首先如果一个矩阵对于上述问题有解,那么该矩阵一定也能只通过交换行或只交换列来得到解.(该结论还不知道如何证⊙﹏⊙b.)
现在我们假设只交换行来得到解. 那么其实这个问题就是将原矩阵的初始n行重新分配给n个行号,且只有当初始第i行的第j列是1时,初始第i行才有资格被分配到新的第j行.(仔细体会一下这句话).
所以新的二分图左边的点集是初始的行号1-n,右边的点集是新的行号1-n. 且如果初始矩阵(i,j)格子是1,那么左i点就与右j点有一条无向边. 最终我们就是求这个二分图的最大匹配是否==n.(仔细想想是不是).如果等于n,则表示能通过交换得到解.反之,则不行.
假设所求二分图的最大匹配==n. 那么我们根据left数组可以得到一个匹配数组r[n](r[i]==j表初始的第i行应该放到新的第j行去).现在我们如何打印最终的交换序列呢?
我们只需要按选择排序的方式即可.假设当前我们处理第i行,且r[i]!=i(表示初始第i行不应该继续放在新的第i行),那么我们在r[i+1,n]范围内找到r[j]==i的这个j,然后swap(r[i],r[j])即可. 具体体会代码.
AC代码:
忘了打印交换次数,错了…悲剧
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn =100+10;
struct Max_Match
{
int n;
bool g[maxn][maxn];
bool vis[maxn];
int left[maxn];
void init(int n)
{
this->n=n;
memset(g,0,sizeof(g));
memset(left,-1,sizeof(left));
}
bool match(int u)
{
for(int v=1;v<=n;v++)if(g[u][v] && !vis[v])
{
vis[v]=true;
if(left[v]==-1 || match(left[v]))
{
left[v]=u;
return true;
}
}
return false;
}
int solve()
{
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(match(i)) ans++;
}
return ans;
}
}MM;
int main()
{
int n;
while(scanf("%d",&n)==1)
{
MM.init(n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int v;
scanf("%d",&v);
if(v) MM.g[i][j]=true;
}
if(MM.solve()==n)//有解
{
int r[maxn];
for(int i=1;i<=n;i++) r[MM.left[i]]=i;
int ans=0;
int r1[maxn];//临时保存r的数组
memcpy(r1,r,sizeof(r));
for(int i=1;i<=n;i++)if(r1[i]!=i)
for(int j=i+1;j<=n;j++)if(r1[j]==i)
{
ans++;
swap(r1[i],r1[j]);
}
printf("%d\n",ans);
for(int i=1;i<=n;i++)if(r[i]!=i)
for(int j=i+1;j<=n;j++)if(r[j]==i)
{
printf("R %d %d\n",i,j);
swap(r[i],r[j]);
}
}
else printf("-1\n");
}
return 0;
}
分享到:
相关推荐
二分图匹配实例代码及整理 1、匈牙利算法 HDU 1150 #include #include #include using namespace std; int m,n,k; int vis[105]; int mpt[105][105]; int use[105]; int hungary(int x) { for(int i=1;i<m;i++)...
B HDU 5093 Battle ships题意给出一个n行m列的图,*代表海域,o代表冰水,#代表冰山,要想在海域中放置船,保证船与船之间不能相互看到,之间
hdu acm 教案 二分匹配及其应用 hdu acm 教案 二分匹配及其应用
HDU二分匹配及其应用,此PPT是刘春英老师版权所有, 特此贡献给广大编程爱好者,特别是对于ACMer
杭电ACM课件2014版之(HDUACM2010版_13)二分匹配及其应用
本人准备2020年保研机试时刷的题目(虽然最后机试取消了,...来自某中流985,在HDU和vjudge平台上大概刷了400道。本文件地图(excel表格)包含了绝大部分我刷过的题目,笔记中具有思路、代码、总结和心得。 大佬勿入!
HDU的1250,主要是利用高精度加法,但是代码有点繁琐,效率不是很高
HDU1059的代码
杭电ACMhdu1163
hdu1001解题报告
hdu 1574 passed sorce
HDU的一题........HDU DP动态规
hdu acm 教案 搜索入门 hdu acm 教案 搜索入门
hdu2101AC代码
搜索 dfs 解题代码 hdu1241
hdu acm 教案 动态规划(1) hdu acm 教案 动态规划(1)
ACM HDU题目分类,我自己总结的大概只有十来个吧
hdu 5007 Post Robot 字符串枚举。 暴力一下就可以了。
hdu1290 解题报告 献给杭电五十周年校庆的礼物 (切西瓜问题,即平面分割空间)
HDU最全ac代码