做着题吐了,原来有个floyd最小环的东西

​flody最小环板子题,别谢我​

由 于 给 的 数 的 二 进 制 有 63 位 由于给的数的二进制有63位 由于给的数的二进制有63位

给 的 0 去 掉 后 , 每 一 个 数 至 少 在 一 位 二 进 制 上 增 加 1 给的0去掉后,每一个数至少在一位二进制上增加1 给的0去掉后,每一个数至少在一位二进制上增加1

那 么 最 多 需 要 127 个 数 就 会 有 一 位 二 进 制 上 有 3 个 数 包 含 那么最多需要127个数就会有一位二进制上有3个数包含 那么最多需要127个数就会有一位二进制上有3个数包含

这3个数形成了一个最小环

不 满 127 , 由 于 数 据 范 围 这 么 小 , f l o d y 跑 最 小 环 不满127,由于数据范围这么小,flody跑最小环 不满127,由于数据范围这么小,flody跑最小环

因 为 是 无 向 图 , 什 么 拓 扑 排 序 , t a r j a n , d f s 都 很 难 搞 \color{Red}因为是无向图,什么拓扑排序,tarjan,dfs都很难搞 因为是无向图,什么拓扑排序,tarjan,dfs都很难搞

不 会 的 去 学 习 一 下 吧 . 不会的去学习一下吧. 不会的去学习一下吧.

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+10;
const int inf=1e9;
int n,s[maxn],top,a[maxn],b[66],bit[66];
int dis[200][200],mp[200][200];
vector<int>vec[maxn];
void to_fenjie(int x)
{
for(int i=0;i<=63;i++)
if( bit[i]&x ) b[i]++;
}
int floyd()
{
int ans=inf;
for(int k=1;k<=top;k++)
{
for(int i=1;i<k;i++)//找不包含k的两个点,环就是i->k->j->i
for(int j=i+1;j<k;j++)
ans=min( ans,dis[i][j]+mp[i][k]+mp[k][j] );
for(int i=1;i<=top;i++)
for(int j=1;j<=top;j++)
dis[i][j]=min( dis[i][j],dis[i][k]+dis[k][j] );
}
if( ans==inf ) ans=-1;
return ans;
}
signed main()
{
bit[0]=1;
for(int i=1;i<=62;i++) bit[i]=bit[i-1]*2;
cin >> n;
for(int i=1;i<=n;i++)
{
cin >> a[i];
if( a[i] ) s[++top]=a[i];
to_fenjie( a[i] );
}
int num=-1,three=3;
for(int i=0;i<=63;i++)
if( b[i]>=3 ) num=i;
if( num!=-1 )//一定形成最小的3个一组的循环
cout << 3 << endl;
else//去暴力搜索这个最小的圈
{
for(int i=1;i<=top;i++)
for(int j=1;j<=top;j++)
if( i!=j ) dis[i][j]=mp[i][j]=inf;
for(int i=1;i<=top;i++)
for(int j=i+1;j<=top;j++)
if( s[i]&s[j] )
dis[i][j]=dis[j][i]=1,mp[i][j]=mp[j][i]=1;
cout << floyd();
}
}