题目大意
对
01
矩阵
A
,
解题思路
分析一下
A
,
分析清楚题目的本质后,那么思路就清晰了。由于矩阵是对称的,我们只需考虑对角线以上的情况,最后把答案乘2就可以了。
对于不能相等的
代码
//YxuanwKeith
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 1e3 + 5, MAXM = MAXN * MAXN * 4;
int N, Num, Fa[MAXN], Col[MAXN], Cnt[MAXN][2], F[MAXN][MAXN], A[MAXN][MAXN];
int tot, Next[MAXM], Last[MAXN], Go[MAXM];
bool Flag;
int Link(int u, int v) {
Next[++ tot] = Last[u], Last[u] = tot, Go[tot] = v;
}
int Get(int Now) {
return (Fa[Now] == Now) ? Now : Fa[Now] = Get(Fa[Now]);
}
void Dfs(int Now, int Pre) {
Cnt[Num][Col[Now]] ++;
for (int p = Last[Now]; p; p = Next[p]) {
int v = Go[p];
if (v == Pre) continue;
if (Col[v] != -1 && Col[v] == Col[Now]) {Flag = 1; return;}
if (Col[v] != -1) continue;
Col[v] = Col[Now] ^ 1;
Dfs(v, Now);
if (Flag) return;
}
}
void GetBlock() {
memset(Last, 0, sizeof Last);
for (int i = 1; i <= N; i ++) Fa[i] = i;
for (int i = 1; i <= N - 1; i ++)
for (int j = i + 1; j <= N; j ++) {
if (!A[i][j]) continue;
Link(i, j), Link(j, i);
int F1 = Get(i), F2 = Get(j);
if (F1 != F2) Fa[F1] = F2;
}
}
void Work() {
scanf("%d", &N);
Flag = 0;
for (int i = 1; i <= N; i ++)
for (int j = 1; j <= N; j ++) scanf("%d", &A[i][j]);
for (int i = 1; i <= N; i ++) if (A[i][i] == 1) Flag = 1;
tot = Num = 0;
GetBlock();
memset(Col, 255, sizeof Col), memset(Cnt, 0, sizeof Cnt), memset(F, 255, sizeof F);
for (int i = 1; i <= N; i ++)
if (Get(i) == i) {
Num ++, Col[i] = 0;
Dfs(i, 0);
if (Flag) break;
}
if (Flag) {printf("-1\n"); return;}
F[0][0] = 0;
int Ans = 0;
for (int i = 1; i <= Num; i ++) {
for (int j = 0; j <= N; j ++) {
int Num0 = Cnt[i][0], Num1 = Cnt[i][1];
if (j >= Num0 && F[i - 1][j - Num0] != -1) F[i][j] = max(F[i][j], F[i - 1][j - Num0] + Num1);
if (j >= Num1 && F[i - 1][j - Num1] != -1) F[i][j] = max(F[i][j], F[i - 1][j - Num1] + Num0);
if (i == Num) Ans = max(Ans, F[i][j] * j);
}
}
printf("%d\n", Ans * 2 - tot);
}
int main() {
int Test;
scanf("%d", &Test);
for (; Test; Test --) Work();
}