HDU

题意:交换任意两行或两列,使主对角线全为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
");
            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
", len);
        for(int i = 0; i < len; ++i){
            printf("C %d %d
", v[i].first, v[i].second);
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/7154391.html