Codeforces Round #580 (Div. 2) D Shortest Cycle(最小环)

今天药忘吃喽~ 2021-10-12 19:24 262阅读 0赞

题意:给你n个数,如果每两个数且(and)不为0,可以连无向边,求最小环。

分析:最小环可以利用Floyd来搞,n太大,如果n很小就可以直接搞了,考虑把n缩小,因为最小环是3,所有只要某一位的个数大于等于3,那么肯定结果就是3,由容斥原理(鸽巢定理)可知,当非0的个数大于63*2时,肯定会有一个位的个数大于2,或者直接统计每一位的个数也行,这样就可以把n缩小到100多了,直接跑Floyd就好了。

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. const int N=150;
  5. const int M=1e5+5;
  6. ll n,cnt,ans=1e9,a[M],d[N][N],e[N][N];
  7. int main() {
  8. cin>>n;
  9. for(int i=0; i<n; i++) {
  10. ll x;
  11. cin>>x;
  12. if(x) a[cnt++] = x;
  13. }
  14. if(cnt>150) {cout<<"3\n"; return 0;}
  15. for(int i=0; i<cnt; i++) for(int j=0; j<cnt; j++) {
  16. if(i!=j && a[i]&a[j]) d[i][j] = e[i][j] = 1;
  17. else d[i][j] = e[i][j] = 1e9;
  18. }
  19. for(int k=0; k<cnt; k++) {
  20. for(int i=0; i<k; i++)
  21. for(int j=i+1; j<k; j++)
  22. ans = min(ans, e[i][k] + e[k][j] + d[i][j]);
  23. for(int i=0; i<cnt; i++) for(int j=0; j<cnt; j++)
  24. d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
  25. }
  26. if(ans==1e9) cout<<"-1\n";
  27. else cout<<ans<<endl;
  28. return 0;
  29. }

发表评论

表情:
评论列表 (有 0 条评论,262人围观)

还没有评论,来说两句吧...

相关阅读