题意
给出一个数组,数组的数表示一个节点,数组中的数两两进行位且与,如果不等于0就这两个节点相连,找出这些数构成的图的最小的一个环的节点数
思路
首先把这这些数构成一个图,给的数范围是10^18,转化为2进制就是64位,所以只要这些数中不同的数大于128个就肯定有三个节点相连,因为128个节点的数最坏的情况就是每一个数的二进制中只有一个1,且每个数的1都在不同的位上,这时要是有多一个不同的数加进来就二进制肯定带一个1,不管在哪一位上都肯定会有两个数在这位上是1,所以他们三个就成环,而无向图的最小环就是3,所以直接输出3,(然而我比赛时不是这样子写的,我是记录每一个在每位上是否是1,是记一次,如果记录到3次时就输出结果3,虽然也是可以的,但是代码写了一大串,因为想法没有错,所以就构图的代码就没有改成上面的想法)
然后就是在图找最小环,用floyd来找最小环
for(int k = 1; k <= maxx; k++){
for(int i = 1; i < k; i++){
for(int j = i + 1; j < k; j++){
ans = min(ans, dp[i][j] + mapp[i][k] + mapp[k][j]);
}
}
for(int i = 1; i <= maxx; i++){
for(int j = i; j <= maxx; j++){
dp[i][j] = dp[j][i] = min(dp[i][j], dp[i][k] + dp[k][j]);
}
}
}
因为是现学的,所以我就说说我的理解
就是我们每次在枚举k点来构建最短路的时候,小于k的点任意两个点之间的最短路已经求出来了,dp数组代表i到j的最短路,然后我们用k对小于k的点进行枚举,因为还没有把k加入最短路中所以这时候用dp[i][j]+mapp[i][k]+mapp[k][j]就是加入k点后的一个最小环,一直更新最小值即可
代码
#include <bits/stdc++.h>
#define inf 1e8
using namespace std;
long long a[100100];
struct node {
long long a, b;
} c[100];
vector<long long> v;
long long maxx;
int mapp[500][500], ans = inf;
int dp[500][500];
bool vis[100];
int getid(long long x) {
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
}
sort(a + 1, a + 1 + n);
int ok = 0;
int q = 0;
for(int i = 0; i < 500; i++){
for(int j = 0; j < 500; j++){
mapp[i][j] = dp[i][j] = inf;
}
}
for(int i = 1; i <= n; i++) {
long long temp = a[i];
int cnt = 1;
while(temp) {
if(temp % 2) {
if(c[cnt].a == 0) {
c[cnt].a = a[i];
} else if(c[cnt].b == 0) {
c[cnt].b = a[i];
} else {
ok = 1;
}
}
temp /= 2;
cnt++;
}
q = max(cnt, q);
}
if(ok) {
printf("3\n");
return 0;
}
for(int i = 1; i < q; i++) {
if(c[i].a != 0 && c[i].b != 0) {
v.push_back(c[i].a);
v.push_back(c[i].b);
}
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for(int i = 1; i < q; i++) {
if(c[i].a != 0 && c[i].b != 0) {
c[i].a = getid(c[i].a);
c[i].b = getid(c[i].b);
mapp[c[i].a][c[i].b] = mapp[c[i].b][c[i].a] = 1;
dp[c[i].a][c[i].b] = dp[c[i].b][c[i].a] = 1;
maxx = max(maxx, c[i].a);
maxx = max(maxx, c[i].b);
}
}
for(int k = 1; k <= maxx; k++){
for(int i = 1; i < k; i++){
for(int j = i + 1; j < k; j++){
ans = min(ans, dp[i][j] + mapp[i][k] + mapp[k][j]);
}
}
for(int i = 1; i <= maxx; i++){
for(int j = i; j <= maxx; j++){
dp[i][j] = dp[j][i] = min(dp[i][j], dp[i][k] + dp[k][j]);
}
}
}
if(ans == inf) {
printf("-1\n");
return 0;
}
printf("%d\n", ans);
}