题目大意: 给你一个N代表一个N*N的0-1矩阵,问经过怎样的交换才能使得所有对角线上的值都为一,每次交换只能交换任意的行和列。
若无法交换成功则输出 -1.
题目分析:我们把一个图做一次二分匹配,所有的行都匹配到了一个列。若是最大匹配数不能到达n,则说明无论怎么交换都是不能得到对角线全部为一的。当我们匹配完成后,再看每行的匹配值,若是P[i] != i,则进行交换,其实进行的是行交换。在这里可以花个图理解一下。
然后记录交换的过程就是答案了。
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; #define maxn 500 int G[maxn][maxn], vis[maxn]; int P[maxn]; int n, m; bool Find(int u) { for(int i=1; i<=n; i++) { if(G[u][i] && !vis[i]) { vis[i] = true; if(P[i] == -1 || Find(P[i]) ) { P[i] = u; return true; } } } return false; } void solve() { int ans = 0; memset(P, -1, sizeof(P)); for(int i=1; i<=n; i++) { memset(vis, false, sizeof(vis)); if(Find(i)) ans ++; } if(ans < n) { puts("-1"); return ; } int x[maxn], y[maxn], cnt = 0; for(int i=1; i<=n; i++) { if(P[i] == i) continue; for(int j=i+1; j<=n; j++) { if(P[j] == i) { x[cnt] = P[i]; y[cnt++] = P[j]; swap(P[i],P[j]); break; } } } printf("%d ", cnt); for(int i=0; i<cnt; i++) printf("R %d %d ", x[i], y[i]); } int main() { while(scanf("%d",&n) != EOF) { for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) scanf("%d", &G[i][j]); } solve(); } return 0; } /* 3 1 0 1 1 0 1 0 1 0 */