CF101915D Largest Group

有一天,你们学校决定做一些统计。他们想研究男孩和女孩之间的友谊关系,以及这种关系对他们成绩的影响。
你们大学的奇怪之处在于男生和女生的人数完全一样。更正式的说法是,这所大学的男生人数是从1到P,女生人数是从1到P。
我们知道,任何一对男孩肯定是朋友,任何一对女孩肯定是朋友。然而,男孩和女孩并不总是朋友。确切地说,这所大学有一个长度为N的列表,其中包含了男孩和女孩之间的友谊关系。第i个友谊关系是由两个整数bi和gi来描述的,意思是男孩的数字bi和女孩的数字gi是朋友。
你所在大学最感兴趣的统计数据之一,是最大的人群(男孩和女孩),其中任何一对都是朋友。你能编写一个程序来解决这样的问题吗?

其实就是求二分图的最大团

我们用(fa_i)存第i个男生和女生的朋友关系(用二进制表示)

然后(f_s)表示当选这几个男生时女生的状态,所以得到下面的转移方程(可能连方程都不是)

[f_s=f_{s-(1<<x-1)} & fa_i ]

x应该是可以随便找一个在s里的点,我用的是最后一个1的位置

然后有个非常好用的c++内置函数叫__builtin

__builtin_popcount返回用二进制表示下1的个数,__builtin_ffs返回二进制表示下最后一个1的位置(注意是位置)

Code(不要在意码风,应该都能看得懂QAQ)

%:include <iostream>
%:include <cstdio>
%:include <algorithm>
%:include <cstring>
%:include <vector>
const int N = 20;
using namespace std;
int T,n,m,fa<:N + 5:>,f[(1 << N) + 5],ans;
int main()
<%
    scanf("%d",bitand T);
    while(T--)
    <%
        scanf("%d%d",bitand n,bitand m);
        int u,v;
        memset(fa,0,sizeof(fa));
        for (int i = 1;i <= m;i++)
        <%
            scanf("%d%d",bitand u,bitand v);
            fa<:u:> or_eq (1 << v - 1);
        %>
        ans = n;
        f<:0:> = (1 << n) - 1;
        for (int i = 1;i < (1 << n);i++)
        <%
            int x = __builtin_ffs(i);
            f<:i:> = f<:i xor (1 << x -1):> bitand fa<:x:>;
            ans = max(ans,__builtin_popcount(i) + __builtin_popcount(f<:i:>));
        %>
        printf("%d
",ans);
    %>
    return 0;
%>
原文地址:https://www.cnblogs.com/sdlang/p/13068279.html