codeforces 1206D Shortest Cycle 解题报告
解题思路:用floyd算法,然而n大了会超时,所以要优化思路,log2(10^18)<60,我们知道n个元素放在
n-1个抽屉里,必然至少有一个抽屉元素数量>=2,所以只要n>120,就必然有3个元素在一个抽屉,即能成环,n在120以下时再用floyd算法判断就行了。注意:忽略所有为0的输入,同时INF不能太大,像0x3f3f3f3f这种3个加起来会爆int数据范围。
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<fstream>
#include<iomanip>
#include<vector>
#pragma warning(disable:4996)
#define INF 300
#define ll long long
#define PI acos(-1.0)
const int N = 200010;
const int maxn = 1e5 + 10;
using namespace std;
int dp[130][130], dis[130][130];
ll a[maxn];
bool cmp(ll a, ll b)
{
return a > b;
}
int main()
{
int n;
scanf("%d", &n);
int cnt = 0;
ll tem;
for (int i = 1; i <= n; i++)
{
scanf("%lld", &tem);
if (tem)
{
cnt++;
a[cnt] = tem;
}
}
if (cnt > 120)
{
printf("3\n");
return 0;
}
else if (cnt < 3)
{
printf("-1\n");
return 0;
}
n = cnt;
sort(a + 1, a + cnt + 1, cmp);
for (int i = 1; i <= cnt; i++)//初始化所有边
{
for (int j = i+1; j <= cnt; j++)
{
if (a[i] & a[j])
{
dp[j][i] = dp[i][j] =1;
}
else
{
dp[j][i] = dp[i][j] = INF;
}
}
}
for (int i = 1; i <= cnt; i++)
{
for (int j = 1; j <= cnt; j++)
{
dis[i][j] = dp[i][j];
}
}
int ans = INF;
for (int k = 1; k <= cnt; k++)
{
for (int i = 1; i < k; i++)
{
for (int j = i + 1; j < k; j++)
{
ans = min(ans, dis[i][j] + dp[i][k] + dp[k][j]);//这里INF大了就爆了
}
}
for (int i = 1; i <= cnt; i++)
{
for (int j = 1; j <= cnt; j++)
{
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);//更新i到j需要经过的边数
}
}
}
if (ans == INF)
printf("-1\n");
else
printf("%d\n", ans);
return 0;
}