Shortest Cycle CodeForces - 1206D

You are given n integer numbers a1,a2,…,an. Consider graph on n nodes, in which nodes i, j (i≠j) are connected if and only if, ai AND aj≠0, where AND denotes the bitwise AND operation.

Find the length of the shortest cycle in this graph or determine that it doesn’t have cycles at all.

Input
The first line contains one integer n (1≤n≤105) — number of numbers.

The second line contains n integer numbers a1,a2,…,an (0≤ai≤1018).

Output
If the graph doesn’t have any cycles, output −1. Else output the length of the shortest cycle.

Examples
Input
4
3 6 28 9
Output
4
Input
5
5 12 9 16 48
Output
3
Input
4
1 2 4 8
Output
-1
Note
In the first example, the shortest cycle is (9,3,6,28).

In the second example, the shortest cycle is (5,12,9).

The graph has no cycles in the third example.

题意给出一组整数,如果两个数按位与运算得到结果为1,那么这两个数代表的下标整数就是相连的;
判断这些下标组成的图中,是否存在环,如果存在求出最小环;

思路:
数据太大,如果暴力建图肯定会T,看了网上大佬的解释之后茅塞顿开,只要二进制的某一位上数字“1”出现的次数大于2次,那么结果一定为3;(更神奇的是,当n>62*2时,结果一定时3;大佬说的,很666);然后处理之后建成图,用Floyd算法求出最小环;(刚学的Floyd,,,,)

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
ll a[100010];
ll dis[201][201];
ll w[201][201];
int main()
{
	int n;
	scanf("%d",&n);
	int cot=1;
	for(int i=0;i<200;i++)
		for(int j=0;j<200;j++) dis[i][j]=w[i][j]=INF;
	for(int i=0;i<n;i++)
	{
		ll x;
		scanf("%lld",&x);
		if(x==0) continue;
		a[cot++]=x;
	}
	if(cot>130) printf("3\n");
	else
	{
		ll ans=INF;
		for(int i=1;i<cot;i++)
			for(int j=i+1;j<cot;j++)
				if(a[i]&a[j]) dis[i][j]=dis[j][i]=w[i][j]=w[j][i]=1;
		for(int k = 1; k <= cot; k++) {//Floyd求最小环 
			for(int i = 1; i < k; i++) for(int j = i + 1; j < k; j++) {
				ans = min(ans, dis[i][j] + w[i][k] + w[k][j]);//找最小环 
			}	
			
			for(int i = 1; i <=cot; i++) for(int j = 1; j <= cot; j++)
				dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);//松弛走最短路 
		}
	if(ans==INF) printf("-1\n");
	else printf("%lld\n",ans);
	}
}

关于循环里面求最小环和松弛走最短路的语句不能像下面一样放在一个循环里面实现,因为当前选择的是k结点之前的点(包括k结点),其他节点不可用;

		for(int k=1;k<=cot;k++) {//Floyd求最小环 
			for(int i=1;i<=cot;i++)
			{
				for(int j=1;j<=cot;j++)
				{
					dis[i][j]=min(dis[i][j], dis[i][k]+dis[k][j]);//松弛走最短路 
					ans=min(ans, dis[i][j]+w[i][k]+w[k][j]);//找最小环 
					
				} 
			}
		} 
发布了197 篇原创文章 · 获赞 36 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43872728/article/details/103327868
今日推荐