ある1頂点だけから複数本の辺が出ている
辺が1つしかない
辺が1つもない
ある3頂点が3辺で結ばれている。
の4パターンを数える。
const int M = 60;
lli nCk[M][M];
void f(void)
{
for (int i = 0; i < M; ++i) {
nCk[i][i] = nCk[i][0] = 1;
}
for (int i = 0; i < M; ++i) {
for (int j = 1; j < i; ++j) {
nCk[i][j] = nCk[i - 1][j - 1] + nCk[i - 1][j];
}
}
return ;
}
class PenguinSledding {
public:
long long countDesigns(int numcp,
vector <int> cp1,
vector <int> cp2)
{
f();
const int N = numcp;
vector<int> g[N];
for (int i = 0; i < cp1.size(); ++i) {
--cp1[i];
--cp2[i];
}
bool adj[M][M];
fill(&adj[0][0], &adj[M - 1][M - 1] + 1, false);
for (int i = 0; i < cp1.size(); ++i) {
g[cp1[i]].push_back(cp2[i]);
g[cp2[i]].push_back(cp1[i]);
adj[cp1[i]][cp2[i]] = adj[cp2[i]][cp1[i]] = true;
}
lli sum = cp1.size() + 1; // 1-edge, no-edge
for (int i = 0; i < N; ++i) {
for (int j = 2; j <= g[i].size(); ++j) {
sum += nCk[g[i].size()][j];
}
}
for (int i = 0; i < N; ++i) {
for (int j = i+1; j < N; ++j) {
for (int k = j+1; k < N; ++k) {
if (adj[i][j] && adj[j][k] && adj[k][i]) ++sum;
}
}
}
return sum;
}
};