zoukankan      html  css  js  c++  java
  • CodeForces 987 F AND Graph

    AND Graph

    题意:给你一个n,一个m,m < 2^n, 然后就是如果 x & y == 0 的话就可以将这2个数连起来, 求最后的有几块。

    题解:对于一个数 11000 则 他必定可以 与 00111相链接, 那么也一定可以和00111中间少了任何几个1的数相连。

    任何我们对于任意一个数都跑出他的父亲 他的父亲就比他多一个1。

    如 00001 他的父亲可以为 10001 01001 00101 00011 这4个, 至于 10101 则是 10001(00101)的父亲。

    但是,对于一个数来说,他不能直接和他的父节点链接,必须要父节点先和别的数链接,然后子节点就一定可以和父节点链接的那个数链接。

    我们先从小到大跑出所有的可以父节点,开另外一个数组去标记。

    然后我们从大的数先开始处理,这样我们就会先访问到祖先节点,再访问到子节点,这样可以保证,我们访问到子节点的时候,他的父节点已经处理过了,我们可以得知这2个点是否可以相连接。

    对于处理到每一个点,我们先找他的所有父节点,如果可以链接,就直接链接,如果他不能和父节点链接,就去找他的对立节点(即0->1, 1->0),看看这2个点是否可以链接,可以就相连,不可以就将这个节点标记为-1,即没有链接的节点,从而当该节点的子节点访问的时候,就可以得知不能链接。

    然后链接的时候用并查集链接块,最后看有几个联通块就是答案了。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
     4 #define LL long long
     5 #define ULL unsigned LL
     6 #define fi first
     7 #define se second
     8 #define pb push_back
     9 #define lson l,m,rt<<1
    10 #define rson m+1,r,rt<<1|1
    11 #define max3(a,b,c) max(a,max(b,c))
    12 #define min3(a,b,c) min(a,min(b,c))
    13 #define _S(X) cout << X << ' ';
    14 #define __S(X) cout << X << endl;
    15 typedef pair<int,int> pll;
    16 const int INF = 0x3f3f3f3f;
    17 const LL mod =  (int)1e9+7;
    18 const int N = (1<<22) + 100;
    19 bool vis[N], vis1[N];
    20 int pre[N];
    21 int Find(int x){
    22     if(x == pre[x]) return x;
    23     return pre[x] = Find(pre[x]);
    24 }
    25 int main(){
    26     int n, m, t, to, u, v;
    27     scanf("%d%d", &n, &m);
    28     int Max = (1<<n) - 1;
    29     for(int i = 1; i <= m; i++){
    30         scanf("%d", &t);
    31         vis[t] = 1;
    32     }
    33     for(int i = 0; i <= Max; i++){
    34         vis1[i] |= vis[i];
    35         if(vis1[i]) {
    36             for(int j = 0; j < n; j++)
    37                 vis1[i|(1<<j)] = 1;
    38         }
    39     }
    40     bool f = 0;
    41     for(int i = 0; i <= Max; i++) pre[i] = i;
    42     for(int i = Max; i >= 0; i--){
    43         if(!vis1[i]){
    44             pre[i] = -1;
    45             continue;
    46         }
    47         f = 0;
    48         for(int j = 0; j < n; j++){
    49             if(i&(1<<j)) continue;
    50             to = i|(1<<j);
    51             if(pre[to] != -1){
    52                 u = Find(i);
    53                 v = Find(to);
    54                 pre[u] = v;
    55                 f = 1;
    56             }
    57         }
    58         if(!f){
    59             to = Max ^ i;
    60             if(vis1[to]) {
    61                 u = Find(i);
    62                 v = Find(to);
    63                 pre[u] = v;
    64             }
    65             else pre[i] = -1;
    66         }
    67     }
    68     int ans = 0;
    69     for(int i = 0; i <= Max; i++){
    70         if(vis[i] && pre[i] == -1) ans++;
    71         if(pre[i] == i) ans++;
    72     }
    73     printf("%d
    ", ans);
    74     return 0;
    75 }
    CF 987 F
  • 相关阅读:
    用友U8 | 【出纳管理】添加日记账时,为什么日期选不了之前的日期?
    用友U8 | 【总账】结账时提示:该凭证已被别的用户锁定,请稍候在试...
    用友U8 | 【实施导航】实施导航进度条一直显示没完成
    利用Action方法委托重构switch接口
    关于wcf序列化后的压缩示例
    sql常用的命令
    WebBrowser通过cookie自动登录网站
    SqlServer大数据的分区方案
    WebBrowser 登录windows集成验证的网站
    SQL大批量插入数据的方式(多表关联) .
  • 原文地址:https://www.cnblogs.com/MingSD/p/9113787.html
Copyright © 2011-2022 走看看