#include "supertrees.h"
#include <bits/stdc++.h>
using namespace std;
int construct(vector<vector<int>> p) {
int n = p.size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (p[i][j] == 3) {
return 0;
}
}
}
vector<int> grp(n);
for (int i = 0; i < n; i++) {
grp[i] = i;
}
auto fnd = [&] (auto &&self, int a) {
if (grp[a] == a) {
return a;
} else {
return grp[a] = self(self, grp[a]);
}
};
vector<vector<int>> edge(n, vector(n, 0));
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (p[i][j] == 1) {
int x = fnd(fnd, i), y = fnd(fnd, j);
if (x != y) {
edge[i][j] = edge[j][i] = 1;
grp[x] = y;
}
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (p[i][j] == 0 && fnd(fnd, i) == fnd(fnd, j)) {
return 0;
}
}
}
vector<vector<int>> gvx(n);
for (int i = 0; i < n; i++) {
gvx[fnd(fnd, i)].push_back(i);
}
sort(gvx.begin(), gvx.end(), [] (vector<int> a, vector<int> b) {
if (a.empty()) {
return false;
} else if (b.empty()) {
return true;
} else {
return a[0] < b[0];
}
});
while (gvx.back().empty()) {
gvx.pop_back();
}
for (int i = 0; i < (int)gvx.size(); i++) {
for (int u : gvx[i]) {
grp[u] = i;
if (p[u] != p[gvx[i][0]]) {
return 0;
}
}
}
int m = gvx.size();
vector<vector<int>> q(m, vector(m, 0));
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
if (i == j) {
q[i][j] = 1;
} else {
q[i][j] = p[gvx[i][0]][gvx[j][0]];
}
}
}
grp.clear(), grp.resize(m);
for (int i = 0; i < m; i++) {
grp[i] = i;
}
for (int i = 0; i < m; i++) {
for (int j = i + 1; j < m; j++) {
if (q[i][j] == 2) {
int x = fnd(fnd, i), y = fnd(fnd, j);
grp[x] = y;
}
}
}
vector<bool> vis(m);
for (int i = 0; i < m; i++) {
if (!vis[i]) {
vector<int> cyc = {i};
vis[i] = true;
for (int j = i + 1; j < m; j++) {
int x = fnd(fnd, i), y = fnd(fnd, j);
if (x == y) {
cyc.push_back(j);
vis[j] = true;
}
}
if (cyc.size() == 1) {
continue;
}
if (cyc.size() == 2) {
return 0;
}
for (int u : cyc) {
for (int v : cyc) {
if (u != v && q[u][v] != 2) {
return 0;
}
}
}
for (int i = 1; i < (int)cyc.size(); i++) {
int u = gvx[cyc[i]][0], v = gvx[cyc[i - 1]][0];
edge[u][v] = edge[v][u] = 1;
}
int u = gvx[cyc[0]][0], v = gvx[cyc.back()][0];
edge[u][v] = edge[v][u] = 1;
}
}
build(edge);
return 1;
}