题目
https://codeforces.com/contest/1206/problem/D
题意
给你n个数 如果两个数 与运算 不为0 那么就存在一条边 问这n个数的最小环
思路
与运算不为0 即存在某一个二进制位都为1 让每个数与二进制为1的相连 如果每个二进制数为1的数存在三个以上 答案即为3
否则floyd跑最小环
注意 三倍的0x3f3f3f3f会爆int
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
typedef long long ll;
ll a[maxn];
int n;
vector<ll> q[80];
vector<int> G[maxn];
map<int,int> mp;
int e[300][300];
int dis[300][300];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i = 1;i <= n;i++)
{
cin>>a[i];
}
for(int i = 1;i <= n;i++)
{
for(int j = 0;j <= 62;j++)
{
if((a[i]>>j)&1)
{
q[j].push_back(i);
}
}
}
for(int i = 0;i <= 62;i++)
{
if(q[i].size() > 2)
{
cout<<3<<endl;
return 0;
}
}
int p = 0;
for(int i = 0;i <= 62;i++)
{
if(q[i].size() == 2)
{
int x = q[i][0];
if(mp[x] == 0) mp[x] = ++p;
x = q[i][1];
if(mp[x] == 0) mp[x] = ++p;
}
}
for(int i = 1;i <= p;i++)
{
for(int j = 1;j <= p;j++)
{
if(i == j) e[i][j] = dis[i][j] = 0;
else e[i][j] = dis[i][j] = 0x3f3f3f;
}
}
for(int i = 0;i <= 62;i++)
{
if(q[i].size() == 2)
{
int u = mp[q[i][0]];
int v = mp[q[i][1]];
e[u][v] = e[v][u] = dis[u][v] = dis[v][u] = 1;
}
}
int ans = 0x3f3f3f;
for(int k=1; k<=p; ++k)
{
for(int i=1; i<k; ++i)
for(int j=i+1; j<k; ++j)
ans=min(ans,dis[i][j]+e[i][k]+e[k][j]);
for(int i=1; i<=p; ++i)
for(int j=1; j<=p; ++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
if(ans == 0x3f3f3f) cout<<"-1"<<endl;
else cout<<ans<<endl;
return 0;
}