CF1205B Shortest Cycle(Floyd 求最小环+推理)题解

思路

看到是无向图最小环,考虑\(Floyd\),但是\(n^3\)的复杂度太高了,怎么办?

观察题面,发现两个数只要与起来是\(1\)就有边,进而想到只要有一个二进制位有三个以上的数字是\(1\),就能构成\(3\)元环。考虑最坏情况,即每个位都只有两个数为\(1\),就有\(64 \times 2=128\)种,那么只要\(n>128\)(准确地说是有效的数字\(>128\))就肯定能构成\(3\)元环。而\(n\leq 128\)的数据就能\(n^3\)过了。

然而

你会发现#16RE了,百思不得其解以后点开第十六个点,发现是一堆\(0\),而全\(0\)的情况是不会输出\(3\)的,因此会爆数组。所以需要在读入的时候把\(0 \)滤掉。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int maxn = 300, maxm = 3e5 + 10;
const int INF = 70000000;
int n;
long long f[maxn][maxn],a[maxn][maxn],val[maxm];

int main(){
    scanf("%d", &n);
    int cnt = 0;
    for(int i = 1; i <= n; ++ i){
        scanf("%lld", &val[i]);
        if(val[i]) cnt ++;
        if(!val[i]) i--, n--;  //把0滤掉
        if(cnt >= 129){ printf("3\n"); return 0;}
    }
    for(int i = 1; i <= n; ++ i)
        for(int j = 1; j <= n; ++ j){
            if((val[i] & val[j]) != 0 && i != j) a[i][j] = f[i][j] = 1;
            else a[i][j] = f[i][j] = INF;
        }
    long long ans = INF;
    for(int k = 1; k <= n; ++ k){
        for(int i = 1; i <= n; ++ i)
            for(int j = 1; j <= n; ++ j)
                if(i != j && j != k && i != k)
                    ans = min(ans, f[i][j] + a[i][k] + a[k][j]);
        for(int i = 1; i <= n; ++ i)
            for(int j = 1; j <= n; ++ j)
                f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
    } 
    if(ans == INF) ans = -1;
    printf("%lld\n", ans);
    return 0;
}
posted @ 2020-11-09 08:07  When_C  阅读(68)  评论(0编辑  收藏  举报