原題連接:CF1205B
ios
給定\(n\)個整數\(a_1,a_2,a_3, \dots ,a_n\),若\(i \neq j\)且\(a_i \land a_j \neq 0\),則節點\(i\)和節點\(j\)相連通。求最小環大小。
\(1 \leq n \leq 10^5\),\(0 \leq a_i \leq 10^{18}\)。spa
題目中的\(a_i\)都在long long的範圍內,即\(a_i \in [0, 2^{64})\),則根據容斥原理可得,若集合\(\{ a_i | a_i \neq 0 \}\)的大小\(n\)知足\(n > 128\),必定有節點數爲\(3\)的環。
不然,跑一次Floyd求最小環便可。code
// luogu-judger-enable-o2 #include <iostream> #include <cstdio> #include <cstring> #define MAX_N (130 + 5) using namespace std; int n; long long a[MAX_N]; int w[MAX_N][MAX_N], dis[MAX_N][MAX_N]; int ans = 2000000000; int main() { scanf("%d", &n); long long tmp; for (int i = 1; i <= n; ++i) { scanf("%lld", &a[i]); if (!a[i]) --i, --n; if (i > 128) return printf("3"), 0; } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if (i != j && (a[i] & a[j])) w[i][j] = 1; else w[i][j] = 100000000; } } memcpy(dis, w, sizeof w); for (int k = 1; k <= n; ++k) { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if (i == k || i == j || j == k) continue; ans = min(ans, dis[i][j] + w[i][k] + w[k][j]); } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); } } } if (ans > n) printf("-1"); else printf("%d", ans); return 0; }