zoukankan      html  css  js  c++  java
  • codeforce D. Shortest Cycle(floyd求最短环)

    题目链接:http://codeforces.com/contest/1206/problem/D

    给n个点,如果点a[ i ] &a[ j ] 不为0,则点a[ i ] 和 a[ j ] 直接可以连接双向边,如果这些点形成的图中有环,求最短路径的环,如果没有输出-1.

    思路:整体是用floyd求最短环,但是数据量很大,有1e5的数据,空跑floyd直接超时,但是由于题目的特殊性,两数相与不为0才有边,那么任意的a[ i ]二进制是有63位的,那么一个数字的二进制最多有63个1,如果总体数字的二进制63位中的任意一位存在三个以上的1,说明有三个数相与都是不为0的,三个数可以互相连边,那么最短环一定是3,靠这个结论解答可以大大缩短时间复杂度,如果a[ i ](不为0)个数多到某一个Max值时,则某一位上1的个数一定会超过3,那么这个Max值具体是多少呢?没有详细计算,但是一定不会超过63 * 2 = 126个,因为就算每一位分配2个“1”,第127个必定使得一位有3个“1”,那么可以将Max可以暂定为126,也就是说1e5的计算数据大大减少到了126,这样跑floyd就不会超时了。注意如果a[ i ] = 0,直接可以不会加入cnt计数中,因为0与任意数相与都是0.

    AC代码:

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<cstring>
    #define maxn 100005
    #define inf 0x3f3f3f3f
    using namespace std;
    long long int a[maxn];
    long long int dist[200][200];
    long long int g[200][200];
    int n;
    int cnt = 1;
    long long int ans = 0x3f3f3f3f;
    void floyd(){
    	for(long long int k = 1;k<=cnt;k++){
    		for(long long int i = 1;i<k;i++){
    			for(long long int j = i+1;j<k;j++){
    				if(dist[i][j] == inf || g[j][k] == inf || g[i][k] == inf){
    					continue;
    				}
    				ans = min(ans,dist[i][j]+g[j][k]+g[k][i]);
    			}
    		}
    		
    		for(long long int i = 1;i<=cnt;i++){
    			for(long long int j = 1;j<=cnt;j++){
    				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    			}
    		}
    	}
    }
    int main(){
    	cin>>n;
    	for(long long int i = 1;i<=n;i++){
    		long long int t;
    		cin>>t;
    		if(t){
    			a[cnt] = t;
    			cnt++;
    		}
    	}
    	if(cnt > 126){
    		cout<<3;
    		return 0;
    	}
    	for(long long int i = 1;i<=cnt;i++){
    		for(long long int j = i+1;j<=cnt;j++){
    			if((a[i] & a[j]) ){
    				dist[i][j] = 1,dist[j][i] = 1;
    				g[i][j] = 1,g[j][i] = 1;
    			}
    			else{
    				dist[i][j] = inf,dist[j][i] = inf;
    				g[i][j] = inf,g[j][i] = inf;
    			}
    		}
    	}
    	floyd();
    	if(ans == inf ){
    		cout<<-1;
    		return 0;
    	}
    	cout<<ans;
    	return 0;
    }
  • 相关阅读:
    PythonのTkinter基本原理
    使用 Word (VBA) 分割长图到多页
    如何使用 Shebang Line (Python 虚拟环境)
    将常用的 VBScript 脚本放到任务栏 (Pin VBScript to Taskbar)
    关于 VBScript 中的 CreateObject
    Windows Scripting Host (WSH) 是什么?
    Component Object Model (COM) 是什么?
    IOS 打开中文 html 文件,显示乱码的问题
    科技发展时间线(Technology Timeline)
    列置换密码
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12129636.html
Copyright © 2011-2022 走看看