題意:給定一個只有0 1的矩形,問能否通過交換行列使對角線上的數全爲1,如果可以輸出交換的路徑。
思路:首先通過匈牙利算法算出最大匹配,如果最大匹配數不等於矩陣的行數,則必然不會成功。只交換行,或者只交換列都可以交換出來。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
int n;
bool path[110][110];
bool used[110];
int match[110];
bool Dfs(int x)
{
for (int i = 1; i <= n; i++)
{
if (!used[i] && path[x][i])
{
used[i]=1;
if (!match[i] || Dfs(match[i]))
{
match[i] = x;
return true;
}
}
}
return false;
}
int Matching()
{
int ans = 0;
memset(match,0, sizeof(match));
for (int i = 1; i <= n; i++)
{
memset(used, false, sizeof(used));
if (Dfs(i))
{
ans++;
}
}
return ans;
}
int main(void)
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while (~scanf("%d", &n))
{
memset(path, false, sizeof(path));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
int x;
scanf("%d", &x);
path[i][j] = x;
}
}
int ans = Matching();
if (ans!=n)
{
printf("-1\n");
continue;
}
int L[110], R[110];
int cnt=0;
for (int i = 1; i <= n; i++)
{
if (match[i] != i)
{
for (int j = 1; j <= n; j++)
{
if (i==match[j])
{
L[cnt] = i;
R[cnt] = j;
cnt++;
swap(match[i], match[j]);
break;
}
}
}
}
printf("%d\n", cnt);
for (int i = 0; i < cnt; i++)
printf("C %d %d\n", L[i], R[i]);
}
return 0;
}