CF 1206D - Shortest Cycle Floyd求最小环

Shortest Cycle

题意

有n(n <= 100000)个数字,两个数字间取&运算结果大于0的话连一条边。问图中的最小环。

思路

可以发现当非0数的个数很大,比如大于200时,一定存在长度为3的环。

如果小于200, 我们就用到了Floyd求最小环的技巧。

#include 
#include  
#include  
#include   
#include   
#include   
#include    
#include    
#include    
#include    <string>
#include    
#include     
#include     
#include     
#include      
#include       
#include       <set>
#include   
#include 
// #include
// 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<<"-----------------------"<#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 pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template
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];
            vectorb;
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) {
                    for(int j=i+1; 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) {
                        for(int j=i+1; 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;
}
View Code

 

你可能感兴趣的:(CF 1206D - Shortest Cycle Floyd求最小环)