HDU - 2819 Swap(二分匹配)
题意:交换任意两行或两列,使主对角线全为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; }