Puoi leggere e provare a risolvere il problema visitando la piattaforma Terry.
Se memorizziamo il grafo con una Matrice di adiancenza possiamo verificare se un certo gruppo di 4 persone forma un "gruppo vacanza perfetto" facendo una piccola osservazione.
Prendiamo ad esempio uno degli input forniti dal problema:
N=5 M=6
4 0
3 4
1 2
1 4
3 2
0 2
Convertendolo in una matrice di adiacenza, otteniamo:
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
0 | ☑️ | ☑️ | |||
1 | ☑️ | ☑️ | |||
2 | ☑️ | ☑️ | ☑️ | ||
3 | ☑️ | ☑️ | |||
4 | ☑️ | ☑️ | ☑️ |
Scegliamo ora un gruppo di 4 amici che indicheremo con [i, j, k, l]
. Possiamo notare che verificare se questo è un "gruppo vacanza perfetto" vuol dire semplicemente verificare che ogni amico abbia un'adiacenza con esattamente 2 dei 3 altri membri del gruppo.
Indicando (come si fa di solito) le adiacenze con valori 0 e 1 nella matrice, quello che dobbiamo verificare è che la somma delle adiacenze sia pari a 2.
La condizione da verificare sarà qualcosa di questo tipo:
condizione = (
adj[i][j] + adj[i][k] + adj[i][l] == 2
&& adj[j][i] + adj[j][k] + adj[j][l] == 2
&& adj[k][i] + adj[k][j] + adj[k][l] == 2
&& adj[l][i] + adj[l][j] + adj[l][k] == 2
);
Una possibile soluzione (non ottimale) è quindi quella di eseguire questo controllo per tutte le possibili quadruple [i, j, k, l]
.
Il controllo si fa in tempo costante (sono una manciata di somme e confronti) ma le quadruple esistenti sono, naturalmente, dell'ordine di . Questa è quindi la complessità della soluzione proposta.
Nota che quando una soluzione quartica può impiegare molto tempo. Certo, è vero che in gara si aveva molto tempo a disposizione per calcolare l'output corretto (potenzialmente anche delle ore) però non è garantito che si riescano a risolvere tutti i testcase nel tempo disponibile.
Invece di provare tutte le quadruple di nodi () proviamo tutte le coppie di archi (). I vantaggi sono che:
Questa soluzione ha complessità ma richiede l'utilizzo delle Liste di adiacenza (in aggiunta alla Matrice di adiacenza che già usiamo) ed un po' più di attenzione nell'implementazione.
#include <iostream>
#include <cstring>
using namespace std;
bool adj[1500][1500];
int solve() {
// Azzera la matrice di adiacenza
memset(adj, 0, sizeof adj);
int N, M;
cin >> N >> M;
for (int i = 0; i < M; ++i) {
int a, b;
cin >> a >> b;
// Riempi la matrice di adiacenza
adj[a][b] = adj[b][a] = 1;
}
int ans = 0;
for (int i = 0; i < N; ++i) {
for (int j = i + 1; j < N; ++j) {
for (int k = j + 1; k < N; ++k) {
for (int l = k + 1; l < N; ++l) {
int c_i = adj[i][j] + adj[i][k] + adj[i][l];
int c_j = adj[j][i] + adj[j][k] + adj[j][l];
int c_k = adj[k][i] + adj[k][j] + adj[k][l];
int c_l = adj[l][i] + adj[l][j] + adj[l][k];
// Controlla che ogni membro abbia esattamente 2 amici
if (c_i == 2 && c_j == 2 && c_k == 2 && c_l == 2) {
ans += 1;
}
}
}
}
}
return ans;
}
int main() {
int T;
cin >> T;
for (int t = 1; t <= T; ++t) {
cout << "Case #" << t << ": " << solve() << endl;
}
}
#include <cstring>
#include <iostream>
#include <numeric>
#include <utility>
#include <vector>
using namespace std;
bool adj[1500][1500];
void solve(int t) {
// Azzera matrice di adiacenza
memset(adj, 0, sizeof(adj));
int N, M;
cin >> N >> M;
vector<pair<int, int>> E;
E.reserve(M);
for (int i = 0; i < M; i++) {
int a, b;
cin >> a >> b;
// Salta archi "equivalenti"
if (adj[a][b]) continue;
// Riempi matrice di adiacenza
adj[a][b] = adj[b][a] = true;
// Popola anche lista di adiacenza
E.emplace_back(a, b);
}
int risposta = 0;
for (int i = 0; i < M; i++) {
auto [a1, b1] = E[i];
for (int j = i + 1; j < M; j++) {
auto [a2, b2] = E[j];
// Evita i casi in cui i due archi non identificano 4 persone diverse
if (a1 == a2 || a1 == b2) continue;
if (b1 == a2 || b1 == b2) continue;
// Controlla queste 4 persone
if (adj[a1][a2] && adj[b1][b2] && !adj[a1][b2] && !adj[b1][a2]) risposta++;
if (!adj[a1][a2] && !adj[b1][b2] && adj[a1][b2] && adj[b1][a2]) risposta++;
}
}
// Dobbiamo dimezzare perché abbiamo contato due volte ogni gruppo
risposta /= 2;
cout << "Case #" << t << ": " << risposta << "\n";
}
int main() {
int T;
cin >> T;
for (int t = 1; t <= T; t++) {
solve(t);
}
}