• hdu5305 Friends[状压dp]


    Friends

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 2329    Accepted Submission(s): 1150


     

    Problem Description

    There are n people and m pairs of friends. For every pair of friends, they can choose to become online friends (communicating using online applications) or offline friends (mostly using face-to-face communication). However, everyone in these n people wants to have the same number of online and offline friends (i.e. If one person has x onine friends, he or she must have x offline friends too, but different people can have different number of online or offline friends). Please determine how many ways there are to satisfy their requirements. 

     

     

    Input

    The first line of the input is a single integer T (T=100), indicating the number of testcases. 

    For each testcase, the first line contains two integers 
    n (1≤n≤8) and m (0≤mn(n−1)2), indicating the number of people and the number of pairs of friends, respectively. Each of the next m lines contains two numbers x and y, which mean x and y are friends. It is guaranteed that xy and every friend relationship will appear at most once. 

     

     

    Output

    For each testcase, print one number indicating the answer.

     

     

    Sample Input

    2

    3 3

    1 2

    2 3

    3 1

    4 4

    1 2

    2 3

    3 4

    4 1

     

     

    Sample Output

    0

    2

     

     

    Author

    XJZX

     

     

    Source

    2015 Multi-University Training Contest 2

     

     

    Recommend

    wange2014   |   We have carefully selected several similar problems for you:  6022 6021 6020 6019 6018 

     

    题目大意:

    给出遮个点遭条边逨n 8,每个边可能是黑色也可能是白色,求每个点相连的边黑边和白边的数量都相等的图有几种。

    思路:

    这个题大家都是用搜索逫剪枝做的,但是知道了这个题的遤遰做法以后真的是让人感叹啊!

    首先,若某个点的度是奇数,就直接不可能了,然后再考虑遤遰的状态!

    我们按照边的顺序一条一条染色(默认所有边原来是白色的),遦遛適遝遛達遝表示染完(染黑或者染白)

    第適条边,状态为達的时候的方法数。

    達由遮个两位的二进制数组成,每两位表示一个点所连的黑边的数目,转移什么的都是显而易见的

    事情,不再多说!

    思考:

    之所以把这个本来是搜索的题的状压遤遰的做法放在这里,主要是因为其体现了状压只是一个手段

    这一点,而且从这个题来看转移的手段是非常灵活的,比如在插头遤遰里常见的四进制,和这个题里面

    的两位二进制,其实有异曲同工之处!

    当然,这种情况下,对位运算的灵活运用就是蛮重要的了,其实呢,个人觉得只要心中把这个数

    当成是二进制数想清楚该怎样使用位运算还是比较容易的!

     

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=51;
    int f[N][1<<17];
    int n,m,T,inc[N];
    struct edge{int x,y;}e[N<<1];
    int main(){
    //    freopen("a.in","r",stdin);
        for(scanf("%d",&T);T;T--){
            scanf("%d%d",&n,&m);
            memset(inc,0,sizeof inc);
            for(int i=1;i<=m;i++){
                scanf("%d%d",&e[i].x,&e[i].y);e[i].x--,e[i].y--;
                inc[e[i].x]++;
                inc[e[i].y]++;
            }
            bool b=0;
            for(int i=0;i<n;i++) if(inc[i]&1){b=1;puts("0");break;}
            if(b) continue;
            memset(f,0,sizeof f);
            f[0][0]=1;
            int ALL=1<<(n<<1);
            for(int i=1;i<=m;i++){
                for(int S=0;S<ALL;S++){
                    f[i][S]+=f[i-1][S];
                    int u=e[i].x;
                    int v=e[i].y;
                    int tu=(S>>(u<<1))&3;
                    int tv=(S>>(v<<1))&3;
                    if(tu+1>(inc[u]<<1)) continue;
                    if(tv+1>(inc[v]<<1)) continue;
                    int su=tu+1;
                    int sv=tv+1;
                    int S0=S^(tu<<(u<<1))^(tv<<(v<<1));
                    S0=S0|(su<<(u<<1))^(sv<<(v<<1));
                    f[i][S0]+=f[i-1][S];
                }
            }
            int S=0;
            for(int i=n-1;~i;i--) S<<=2,S|=inc[i]>>1;
            printf("%d
    ",f[m][S]);
        }
        return 0;
    }
  • 相关阅读:
    解决Linux Ubuntu 突然出现死机无法进入系统的问题(sysrq magic key)
    [python笔记]文件处理
    [python笔记]pandas应用
    将Excel中列数转为列号
    Linq学习笔记
    install chrome for opensuse 12.1
    Word 文档拆分
    原型模式?java深克隆和浅克隆
    单例模式?学习懒汉式和饿汉式
    简单工厂模式?接口引用指向实例对象(面向接口)
  • 原文地址:https://www.cnblogs.com/shenben/p/6707411.html
Copyright © 2020-2023  润新知