D - Largest Group -状压枚举或最大团

  • D - Largest Group

  •  Gym - 101915D 
  • 题意 男生p个,女生p个,男生们相互都为朋友女生们也都是朋友 ,男生女生为朋友会给出关系图
  • 求一个最大的朋友关系集合里面每两个人都相互为朋友,
  • 状压:
  • 二进制枚举所有男生组合情况
  • 位运算辅助求出在每种情况下的 人数为多少,不断维护最大值
  • #include<bits/stdc++.h>
    using namespace std;
    #define ll int
    #define maxn 33
    ll t,n,p,boy[maxn];
    ll temp,u,v,ans;
    int main()
    {
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--)
        {
            ans=0;
            cin>>p>>n;
            for(int i=0; i<=p; i++)
                boy[i]=0;
            while(n--)
            {
                cin>>u>>v;
                boy[u-1]|=(1<<(v-1));
            }
            ll sum=(1<<p)-1;
            for(ll i=1; i<=sum; i++)
            {
                temp=sum;
                for(ll j=0; j<p; j++)
                {
                    if((1<<j)&i)temp&=boy[j];
                }
                ll s=0 ;
                for (s =0; temp; ++s)
                {
                    temp &= (temp -1) ;
                }
                temp=i;
                for (s; temp; ++s)
                {
                    temp &= (temp -1) ;
                }
                ans=max(s,ans);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 最大独立集:
  • 知识:最大团 = 补图G的最大独立集数 ———>最大独立集数 = 补图G'最大团
  • 匈牙利按照非朋友关系 去匹配 在这种情况下的最大独立集 就是 最大的朋友关系网络
  • #include<bits/stdc++.h>
    using namespace std;
    #define maxn 25
    int t,p,n,u,v,ans;
    int mmp[maxn][maxn];
    int match[maxn];
    bool vis[maxn];
    bool dfs(int x)
    {
        for(int i=1; i<=p; i++)
        {
            if(!mmp[x][i]&&!vis[i])
            {
                vis[i]=1;
                if(match[i]==-1||dfs(match[i]))
                {
                    match[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        cin>>t;
        while(t--)
        {
            ans=0;
            cin>>p>>n;
            memset(mmp,0,sizeof(mmp));
            for(int i=1; i<=p; i++)
            {
                match[i]=-1;
                vis[i]=0;
            }
            while(n--)
            {
                cin>>u>>v;
                mmp[u][v]=1;
            }
            for(int i=1; i<=p; i++)
            {
                memset(vis,0,sizeof(vis));
                if(dfs(i))
                    ans++;
            }
            cout<<2*p-ans<<endl;
        }
        return 0;
    }
    
  •  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值