CF 1206D - Shortest Cycle Floyd求最小环
Shortest Cycle
题意
有n(n <= 100000)个数字,两个数字间取&运算结果大于0的话连一条边。问图中的最小环。
思路
可以发现当非0数的个数很大,比如大于200时,一定存在长度为3的环。
如果小于200, 我们就用到了Floyd求最小环的技巧。
#include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> #include <unordered_map> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr << #x << " := " << x << endl; #define bug cerr << "-----------------------" << endl; #define FOR(a, b, c) \ for (int a = b; a <= c; ++a) typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; template <typename T> inline T read(T &x) { x = 0; int f = 0; char ch = getchar(); while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x = f ? -x : x; } /**********showtime************/ const int maxn = 2e5 + 9; ll a[maxn]; int cnt[20]; ll ans; ll dp[209][209], g[209][209]; vector<ll> b; int main() { int n; scanf("%d", &n); int cnt = 0; for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); if (a[i] == 0) cnt++; else b.pb(a[i]); } if (n - cnt > 200) puts("3"); else { int n = b.size(); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i == j) dp[i][j] = 0, g[i][j] = 0; else dp[i][j] = dp[j][i] = inf, g[i][j] = inf; } } for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if ((b[i] & b[j]) > 0) { dp[i + 1][j + 1] = 1; dp[j + 1][i + 1] = 1; g[i + 1][j + 1] = 1; g[j + 1][i + 1] = 1; } } } ans = inf; for (int k = 1; k <= n; k++) { for (int i = 1; i < k; i++) { for (int j = i + 1; j < k; j++) { ans = min(ans, dp[i][j] + g[k][i] + g[k][j]); } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]); } } } if (ans == inf) puts("-1"); else printf("%lld\n", ans); } return 0; }
skr