• 【 思维】【DFS联通块】CF986C AND Graph


    【 思维】【联通块】CF986C AND Graph

    题目大意

    给定两个数n和m。

    现有一个有m个整数构成的集合,每个整数均在0~2^n-1之间,以每个整数为顶点建立一个无向图,当两个整数x,y符合“x&y=0”时,则认为x,y之间存在一条边。这里的“&”表示运算符“且”。计算图中联通块的数量。

    题目思路

    如果x与上y等于0的话,从微观的角度来考虑的话,x的每一位与上对应的y的每一位都会等于0.

    如果x在某一位上为1的话,那么y在那一位上必须为0。

    如果x在某一位上为0的话,那么y在那一位上既可以为0,也可以为1。

    不妨规定n=5,且设\(p=2^n-1=31=11111\)

    不妨设\(x = 10011\),\(y=x\space xor\space p =01100\)

    发现\(x \& y=0\)

    且不妨令\(y_1=01000,y_2=00100\)

    发现\(x \& y_1=0,x\&y_2=0\)

    所以x与上将y在某一个位置本为1后变为0的数\(y_i\)也是符合答案的

    \(y_i\) 也有相对应的可以与起来变成0的数字。

    所以可以使用搜索的做法来完成这道题目。

    搜索的数的类型可以分为两类

    1. 异或上\(2^n-1\)后的数。(凡是这类数都应该搜索)
    2. 异或上\(2^n-1\)后的数的所有的子数(可以每次单变一个1为0就好)(凡是这类数都值得被搜索)

    其他分析

    观察一下数据范围,\(0≤n≤22 , 1 \le m \le 2^{n} \le4194304 \le5e6\)

    代码

    #include <bits/stdc++.h>
    #define ll long long
    #define ull unsigned long long
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define MAX 1000005
    #define MOD 1000000007
    using namespace std;
    const int N = 5E6+500;
    int cnt,p; 
    int n,m;
    bool used[N],mark[N];
    vector<int > vec;
    void dfs(int u)
    {
    	used[u] = 1;
    	mark[u] = 0;
    	if( mark[ u^p ] && !used[ u ^ p ] ) dfs( u^p );
    	//子集 
    	for(int i=0;i<n;i++)
    		if( u & (1<<i) )
    		   if( !used[ u ^ (1<<i) ]) dfs( u ^ (1<<i) );
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        cin>>n>>m;
        p = (1<<n)-1;
        for(int i=1;i<=m;i++)
        {
        	int x;
        	cin>>x;
        	vec.push_back(x);
        	mark[ x ^ p ] = 1;
    	}
    	
    	for(int i=0;i<vec.size();i++)
    	    if(!used[ vec[i] ]) 
    		{
    		   mark[ vec[i] ^ p] = 1;
    		   used[ vec[i] ] = 1;
    		   dfs( vec[i] ^ p );	
    		   cnt++;
    		}
        cout<<cnt;
    	return 0;
    }
    
  • 相关阅读:
    [NOIP2011]选择客栈
    [学习笔记]字符串的一些基本操作
    [学习笔记]树链剖分
    [宁波集训]0827Day1
    [POI2015]LOG(树状数组)
    [学习笔记]树形dp
    货车运输(最大生成树+倍增LCA)
    POJ 3617 Best Cow Line 贪心算法
    C++ STL next_permutation() prev_permutation(a,a+n)用法。
    POJ 2386 Lake Counting dfs
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15928913.html
Copyright © 2020-2023  润新知