W zadaniu mamy nieskierowany graf o
Kluczowa obserwacja jest taka, że wystarczy ograniczyć się do ścieżek długości
co najwyżej
Zliczyć ścieżki o długości 2 jest bardzo prosto -- są to wszystkie krawędzie,
które mają końce różnych kolorów (przy czym każdą krawędź liczymy dwukrotnie,
bo istotny jest również kierunek, w którym przechodzimy ścieżkę).
Zatem czas zliczania tych ścieżek to
Dla ścieżek długości 3 postaci
Dla ścieżek długości 4 postaci
Zauważmy, że powyższe rozwiązania działałyby również, gdybyśmy mieli znajdować ścieżki proste określonej długości, ale liczba różnych kolorów w grafie byłaby większa niż długości ścieżek.
Dla ścieżek długości 5 rozwiązanie jest trochę bardziej skomplikowane
i istotnie korzysta z tego, że ścieżka musi zawierać wszystkie kolory z grafu.
Dla ścieżki
Dodatkowo, wcześniej spamiętujemy sobie liczbę kolorowań podścieżki typu
Poniżej kod, który implementuje wszystkie przypadki:
const int N = 310000, K = 5; int n,m,k,col[N],Neigh[N],neigh[N][K]; int edge[N][1<<K]; vector<int> adj[N]; ll sq(int x) { return ll(x) * x; } int main() { scanf("%d%d%d",&n,&m,&k); REP(i,n) { scanf("%d",&col[i]); --col[i]; } REP(i,m) { int a,b; scanf("%d%d",&a,&b); --a; --b; adj[a].push_back(b); adj[b].push_back(a); } ll ans = 0; // 2 REP(i,n) for (int j : adj[i]) { if (col[i] != col[j]) ++ans; } // 3 REP(i,n) for (int j : adj[i]) { neigh[i][col[j]]++; Neigh[i]++; } REP(i,n) { ans += sq(Neigh[i] - neigh[i][col[i]]); REP(k,K) if (k != col[i]) ans -= sq(neigh[i][k]); } // 4 REP(i,n) for (int j : adj[i]) { if (col[i] != col[j]) { int ci = Neigh[i] - neigh[i][col[i]] - neigh[i][col[j]]; int cj = Neigh[j] - neigh[j][col[j]] - neigh[j][col[i]]; ans += ll(ci) * cj; REP(k,K) if (k != col[i] && k != col[j]) { ans -= ll(neigh[i][k]) * neigh[j][k]; } } } // 5 REP(i,n) for (int j : adj[i]) { if (col[i] != col[j]) { REP(k,K) if (k != col[i] && k != col[j]) { edge[i][(1<<col[j]) | (1<<k)] += neigh[j][k]; } } } REP(i,n) { int k1 = col[i] == 0 ? 1 : 0; REP(k2,K) if (k2 != col[i] && k2 != k1) { int mask1 = (1<<k1) | (1<<k2); int mask2 = (1<<5)-1 - (1<<col[i]) - mask1; ans += 2 * ll(edge[i][mask1]) * edge[i][mask2]; } } printf("%lld\n", ans); }