Hdu 5765 Bonds

来源:互联网 发布:传奇霸业翅膀升级数据 编辑:程序博客网 时间:2024/05/01 09:10

丢链接


check(mask)就是用bfs的方式来检查mask是否联通

具体的,done 是已经访问过的点集,did是可以访问的点集

首先找一个mask的点start加到did

显然donedid的子集,每一次找到一个在did中并且不在done中的点st,把和st直接联通的在mask中的点加到did里面,把st加到done里面,最后的done就是和start联通的点集了


位运算大法好~

#include<bits/stdc++.h>using namespace std;const int bit = 22;const int maxn = 1<<bit;int l[bit*bit],r[bit*bit];int edge[bit];int rev[maxn];int cnt[maxn];int lowbit(int x){    return x & (-x);}bool check(int S){    int done = 0;    int did = lowbit(S);    while(did != done){        int st = rev[lowbit(did ^ done)];        done |= 1<<st;        did |= edge[st] & S;    }    return done == S;}int main(){    int T;    scanf("%d",&T);    int n,m;    int icase = 1;    memset(rev,-1,sizeof(rev));    for(int i=0;i<bit;i++) rev[1<<i] = i;    while(T-- && ~scanf("%d %d",&n,&m)){        memset(edge,0,sizeof(edge));        memset(cnt,0,sizeof(cnt));        for(int i=0;i<m;i++){            scanf("%d %d",&l[i],&r[i]);            edge[l[i]] |= 1<<r[i];            edge[r[i]] |= 1<<l[i];        }        int bnd = (1<<n) - 1;        int all = 0;        for(int i=1;i<bnd;i++){            if((i&1) && check(i) && check(bnd ^ i)){                cnt[i]++,cnt[bnd^i]++;                all++;            }        }        for(int i=1;i<=bnd;i<<=1){            for(int j=0;j<=bnd;j++){                if(i&j)                    cnt[i^j] += cnt[j];            }        }        printf("Case #%d:",icase++);        for(int i=0;i<m;i++){            printf(" %d",all - cnt[(1<<l[i])|(1<<r[i])]);        }        puts("");    }    return 0;
0 0
原创粉丝点击