HDU - 2819 Swap(二分匹配)

时间:2022-05-23 17:44:19

题意:交换任意两行或两列,使主对角线全为1。

分析:

1、主对角线都为1,可知最终,第一行与第一列匹配,第二行与第二列匹配,……。

2、根据初始给定的矩阵,若Aij = 1,则说明第i行与第j列匹配,据此求最大匹配数cnt,若cnt==N,才可通过交换使主对角线都为1。

3、交换时,可只交换行或只交换列。如:只交换列,行不变(顺序为1,2,3,……,n),那么对于列,只需要根据选择排序,将每行一开始匹配的列的顺序最终也变成1,2,3,……,n即可,因为是选择排序,每次选择第i小的交换到第i个位置,因此最多只需要交换N次。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-9;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 100 + 10;
const int MAXT = 1000 + 10;
using namespace std;
int a[MAXN][MAXN];
bool used[MAXN];
int match[MAXN];
vector<pair<int, int> > v;
int N;
bool dfs(int x){
for(int i = 1; i <= N; ++i){
if(a[x][i] && !used[i]){
used[i] = true;
if(match[i] == -1 || dfs(match[i])){
match[i] = x;
return true;
}
}
}
return false;
}
int hungary(){
int cnt = 0;
for(int i = 1; i <= N; ++i){
memset(used, false, sizeof used);
if(dfs(i)) ++cnt;
}
return cnt;
}
int main(){
while(scanf("%d", &N) == 1){
memset(match, -1, sizeof match);
v.clear();
for(int i = 1; i <= N; ++i){
for(int j = 1; j <= N; ++j){
scanf("%d", &a[i][j]);
}
}
int cnt = hungary();
if(cnt != N){
printf("-1\n");
continue;
}
for(int i = 1; i <= N; ++i){
int tmp = i;
for(int j = i + 1; j <= N; ++j){
if(match[tmp] > match[j]) tmp = j;
}
if(tmp == i) continue;
v.push_back(pair<int, int>(i, tmp));
swap(match[i], match[tmp]);
}
int len = v.size();
printf("%d\n", len);
for(int i = 0; i < len; ++i){
printf("C %d %d\n", v[i].first, v[i].second);
}
}
return 0;
}