hdu 2819 Swap
2012-07-09 20:05
162 查看
题目大意:给定一个矩阵,矩阵元素取值为0或1,每次操作可以交换任意两行或两列,要求对于给定矩阵给出操作次数和操作序列将主对角线(A[i][i],i=1...n)元素全部变为1,无法满足则输出-1.
题意分析:首先要意识到如果有解,一定可以全部由行交换或者列交换来完成。不妨以行交换为例,行交换不改变元素的列次序,也就是说,若想A[2][2]为1,必须A[i][2](i=1..n)中有一个或者多个1.那么,如果问题有解,就变成找出一个序列,使得某一个行来满足某一列的对角线值唯一(有点绕口)。或者说,每一次调整一行的位置使得某一列上的对角线元素为1.
进一步抽象,就变成了,把指定的行号分配给指定的列号,如果每个列号都能分配到,那么就有解。就是二分图的最大匹配。匹配数量如果小于n,则无解。
有解时,由于具体匹配情况已经求出,问题就变成给定一个1..N的序列,求出一系列的交换使得序列恢复1,2,3,...,N-1,N的顺序。记录交换次数,然后输出交换次序即可。(具体做法:如果元素s[i]!=i,那么找到s[j]==i将这两个元素交换即可,双重循环)
最后一个问题:是R还是C?我提交的时候写了R,但是wa了,改成C好了。仔细想想,在第一步时,行与列没有区别,行匹配列与列匹配行都一样。这个问题卡了我一下午。仔细思考这个道题:a[i][j]=1到底代表什么?代表:
1.第i行放到第j行可以使得第j行的主对角线为1;
2.第j列放到第i列可以使得第j列的主对角线为1;
也就是说,这道题目中,图是有向的,看你怎么解释。那么,只要确定匈牙利算法得到的匹配次序究竟是什么就可以解释了。
下面一个例子:
4
0 1 0 0
0 0 1 0
0 0 0 1
1 0 1 1
答案:
3 3
C 1 2 R 1 4
C 2 3 R 2 4
C 3 4 R 3 4
match数组:
match [0] [1] [2] [3]
[3] [0] [1] [2]
观察之后发现,A[match[i]][i]=1,也就是说,match数组的方向是由match[i]指向i的。那么按照上面的提出的恢复次序的方法:
每次用对应的x去恢复match[x],那么,输出经该是C
同样的,如果想输出R,就要根据对应的match[x]去恢复x;(偷了个懒,直接写了个最裸的二重循环。通过添加辅助数组利用桶排序的思想应该可以降到1维,再不济也可以写个排序变成n^2/2)
至此,问题全面解决。好久没有把一个题目如此细致的理一遍了。网上搜到的题解都太模糊,知其然不知其所以然。
最后,上代码:
题意分析:首先要意识到如果有解,一定可以全部由行交换或者列交换来完成。不妨以行交换为例,行交换不改变元素的列次序,也就是说,若想A[2][2]为1,必须A[i][2](i=1..n)中有一个或者多个1.那么,如果问题有解,就变成找出一个序列,使得某一个行来满足某一列的对角线值唯一(有点绕口)。或者说,每一次调整一行的位置使得某一列上的对角线元素为1.
进一步抽象,就变成了,把指定的行号分配给指定的列号,如果每个列号都能分配到,那么就有解。就是二分图的最大匹配。匹配数量如果小于n,则无解。
有解时,由于具体匹配情况已经求出,问题就变成给定一个1..N的序列,求出一系列的交换使得序列恢复1,2,3,...,N-1,N的顺序。记录交换次数,然后输出交换次序即可。(具体做法:如果元素s[i]!=i,那么找到s[j]==i将这两个元素交换即可,双重循环)
最后一个问题:是R还是C?我提交的时候写了R,但是wa了,改成C好了。仔细想想,在第一步时,行与列没有区别,行匹配列与列匹配行都一样。这个问题卡了我一下午。仔细思考这个道题:a[i][j]=1到底代表什么?代表:
1.第i行放到第j行可以使得第j行的主对角线为1;
2.第j列放到第i列可以使得第j列的主对角线为1;
也就是说,这道题目中,图是有向的,看你怎么解释。那么,只要确定匈牙利算法得到的匹配次序究竟是什么就可以解释了。
下面一个例子:
4
0 1 0 0
0 0 1 0
0 0 0 1
1 0 1 1
答案:
3 3
C 1 2 R 1 4
C 2 3 R 2 4
C 3 4 R 3 4
match数组:
match [0] [1] [2] [3]
[3] [0] [1] [2]
观察之后发现,A[match[i]][i]=1,也就是说,match数组的方向是由match[i]指向i的。那么按照上面的提出的恢复次序的方法:
for(int i=0;i<n;++i) if(match[i] != i) for(int j=i+1;j<n;++j) if(match[j]==i) { printf("C %d %d\n",i+1,j+1); match[j]=match[i]; }
每次用对应的x去恢复match[x],那么,输出经该是C
同样的,如果想输出R,就要根据对应的match[x]去恢复x;(偷了个懒,直接写了个最裸的二重循环。通过添加辅助数组利用桶排序的思想应该可以降到1维,再不济也可以写个排序变成n^2/2)
for(int i=0;i<n;++i) for(int j=0;j<n;++j) if(match[i]!=i) { printf("R %d %d\n",match[i]+1,match[match[i]]+1); swap(match[match[i]],match[i]); }
至此,问题全面解决。好久没有把一个题目如此细致的理一遍了。网上搜到的题解都太模糊,知其然不知其所以然。
最后,上代码:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int maxn = 105; int g[ maxn ][ maxn ]; int vis[ maxn ], match[ maxn ],tmp[ maxn ]; int n; int find( int from ) { for( int i = 0; i < n; ++i ) { if( g[ from ][ i ] && !vis[ i ] ) { vis[ i ] = 1; if( match[ i ] == -1 || find( match[ i ] ) ) { match[ i ] = from; return 1; } } } return 0; } int Hungray( ) { int sum = 0; memset( match, -1, sizeof( match ) ); for( int i = 0; i < n; ++i ) { memset( vis, 0, sizeof( vis ) ); if( find( i ) ) sum ++; } return sum; } int main() { while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;++i) for(int j=0;j<n;++j) scanf("%d",&g[i][j]); if(Hungray()<n) printf("-1\n"); else { int ans=0; for(int i=0;i<n;++i) tmp[i]=match[i]; for(int i=0;i<n;++i) for(int j=0;j<n;++j) if(tmp[i]!=i) { ++ans; swap(tmp[tmp[i]],tmp[i]); } printf("%d\n",ans); for(int i=0;i<n;++i) for(int j=0;j<n;++j) if(match[i]!=i) { printf("R %d %d\n",match[i]+1,match[match[i]]+1); swap(match[match[i]],match[i]); } //for(int i=0;i<n;++i) // if(tmp[i] != i) // for(int j=i+1;j<n;++j) // if(tmp[j]==i) // { // ++ans; // tmp[j]=tmp[i]; // } //printf("%d\n",ans); //for(int i=0;i<n;++i) // if(match[i] != i) // for(int j=i+1;j<n;++j) // if(match[j]==i) // { // printf("C %d %d\n",i+1,j+1); // match[j]=match[i]; // } } } }
相关文章推荐
- hdu 2819 Swap
- HDU 2819 Swap 【二分图匹配 交换方法】
- Swap——hdu 2819
- HDU 2819 Swap【二分图|启发题】
- hdu2819 Swap--最大匹配数
- hdu 2819 Swap
- HDU 2819 ——Swap——————【最大匹配、利用linker数组、邻接表方式】
- HDU 2819 Swap【二分图|启发题】
- hdu 2819 Swap (二分图匹配)
- E - Swap - hdu 2819(简单二分图匹配)
- hdu 2819 Swap
- HDU 2819 Swap (二分匹配+破输出)
- HDU 2819 Swap [二分图匹配]
- hdu 2819 Swap
- HDU 2819 Swap (最大二分匹配+输出路径)
- HDU 2819 Swap(最大匹配问题)
- HDU 2819 swap(二分图匹配并记录路径)
- HDU 2819 Swap(二分图匹配)
- HDU-2819 swap(二分图最大匹配)
- Swap HDU - 2819