一开始没想到是二分图匹配,yy了一个贪心算法。
后来发现bug
4
1 0 0 1
0 1 0 1
1 1 1 0
1 0 1 0
不过总觉得改进一下可以ac
代码先留着~
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
#define REP(i,s,t) for(int (i)=(s);(i)<=(t);++(i))
typedef long long LL;
const int maxn = 30000;
int n;
int m[105][105];
int r[105];
int pos[105];
int a[105];
int save[1000][2];
bool vis[105];
int main() {
freopen("input.in", "r", stdin);
while(cin >> n) {
//cout << n << endl;
REP(i, 0, n-1) {
REP(j, 0, n-1) {
scanf("%d",&m[i][j]);
}
}
bool can = true;
REP(i, 0, n-1) {
bool ok = false;
REP(j, 0, n-1)
if (m[i][j] == 1) {
ok = true;
break;
}
if (!ok) {
can = false;
break;
}
}
REP(i, 0, n-1) {
bool ok = false;
REP(j, 0, n-1)
if (m[j][i] == 1) {
ok = true;
break;
}
if (!ok) {
can = false;
break;
}
}
if (!can) {
cout << -1 << endl;
continue;
}
REP(i, 0, n-1) r[i] = i;
//sort(r, r+n, cmp);
memset(vis, false, sizeof(vis));
REP(i, 0, n-1) {
int idx = 0, _min = 0x7FFFFFFF;
REP(j, 0, n-1)
if (!vis[j] && m[j][i]) {
int point = 0;
REP(k, 0, n-1) if (k != i && m[j][k]) {
int cnt = 0;
REP(l, 0, n-1)
if (m[l][k])
++cnt;
if (cnt == 1)
point += 1000;
else if (cnt > 0)
point += (n-cnt)*10;
}
if (point < _min) {
_min = point;
idx = j;
}
}
vis[idx] = true;
r[i] = idx;
}
//REP(i, 0, n-1) cout << v[r[i]] << endl;
//REP(i, 0, n-1) cout << r[i] << ' ' ;cout << endl;
REP(i, 0, n-1) {pos[i] = i;a[i] = i;}
int ans_cnt = 0;
REP(i, 0, n-1)
if (a[i] != r[i]) {
save[ans_cnt][0] = i+1;
save[ans_cnt++][1] = pos[r[i]]+1;
//cout << "R " << a[i]+1 << ' ' << pos[r[i]]+1 << endl;
int tmp = a[i];
a[i] = r[i];
a[pos[r[i]]] = tmp;
pos[tmp] = pos[r[i]];
pos[r[i]] = i;
}
cout << ans_cnt << endl;
REP(i, 0, ans_cnt-1)
printf("R %d %d\n",save[i][0],save[i][1]);
}
return 0;
}