zoukankan      html  css  js  c++  java
  • Codeforces986C AND Graph 【位运算】【dfs】

    题目大意:

    一张$ m $个编号互异点图,最大不超过$ 2^n $,若两个编号位与为0则连边,问连通块数量。

    题目分析:

    考虑怎样的两个点会连边。这种说法对于A和B两个点来说,就相当于B在A的0的子集中。我们不妨将A的0用1填充,得到的每一个数取反都是可以与A连边的点,然后这个取反前的数也可以继续填充。重新审视它发现我们从小到大地考虑每个0被1填充是没关系的,因为我们很显然地遍历了所有情况。那么可以做记忆化。时间复杂度$O(n2^n)$.

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = 4250000;
     5 
     6 int n,m,ans;
     7 int a[maxn],app[maxn];
     8 int arr[maxn][2];
     9 
    10 void dfs(int now,int dr){
    11     if(arr[now][dr] == 1) return;
    12     arr[now][dr] = 1;
    13     for(int i=0;i<n;i++){
    14     if(((1<<i) & now) == 0){
    15         dfs(now|(1<<i),dr);
    16     }
    17     }
    18     if(app[(1<<n)-1-now]) arr[(1<<n)-1-now][0] = 1,dfs((1<<n)-1-now,1);
    19 }
    20 
    21 void work(){
    22     for(int i=1;i<=m;i++){
    23     if(!arr[a[i]][0]){
    24         ans++;arr[a[i]][0] = 1;
    25         dfs(a[i],1);
    26     }
    27     }
    28 }
    29 
    30 int main(){
    31     scanf("%d%d",&n,&m);
    32     for(int i=1;i<=m;i++) scanf("%d",&a[i]),app[a[i]] = 1;
    33     work();
    34     printf("%d",ans);
    35     return 0;
    36 }
  • 相关阅读:
    Oracle 备份与恢复介绍
    Oracle 监听器
    ORA-01041: 内部错误,hostdef 扩展名不存在
    NIO读写文件并加锁
    ActiveMQ消息生产消费流程
    金额,有效值等保留小数位处理
    JVM
    Linux架构分布式集群之基础篇
    Vue.js 开发实践:实现精巧的无限加载与分页功能
    Mysql 查看连接数,状态
  • 原文地址:https://www.cnblogs.com/Menhera/p/9116600.html
Copyright © 2011-2022 走看看