Luo Gu P2423 [HEOI2012] circle of friends

Subject to the effect:

There \ (A, B \) two set points, each point a little right, in \ (A \) set, there are two points between the edges meet \ (a_i \ xor \ a_j \ mod \ 2 = 1 \ ) , in \ (B \) set, there are two points between the edges meet \ (b_i \ xor \ b_j \ mod \ 2 = 0 \) or \ (b_i \ or \ b_j \ ) into an odd number of binary \ (1\)

Seeking \ (A, B \) size of the set of the largest groups

The first type data: \ (| A | \ Le 200 is, | B | \ Le 200 is \)
second type data: \ (| A | \ Le 10, | B | \ Le 3000 \)

At present the algorithm represents the maximum clique problem is \ (NPC \) problem, so we can not directly address

but weMaybeWe know that the biggest group = maximum independent set up of FIG.

Consider the establishment of seeking complementary graph largest independent set

For \ (A \) set, there are different between the original parity point edge is supplemented in FIG between all sides have the same parity point, there is no edge between different parity points, for a maximum independent set of Complement , \ (A \) FIG selected from up to two

For \ (B \) set in the bordered between the original point of the same parity, the parity of different points of some edges, then fill in the figures, there is no edge between the same point of parity, the parity we can criteria for the classification up into the bipartite graph in FIG.

Building up a rear view as \ (A \) set points less, we can enumerate \ (A \) set of selected points, and those points then complete configuration of FIG \ (B \) set point markers, run bipartite graph maximum independent set

Often a little card, stamped optimization

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
namespace red{
#define eps (1e-8)
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=3010;
    int haku;
    int n,m,k,ret,tim,tim2;
    int T[N];
    int ap[N],bp[N];
    bool jx[N][N];
    bool jxb[N][N];
    int vis[N<<2],f[N<<2];
    int t3[N<<2];
    int py[N],num;
    int ans;
    int head[N],cnt;
    struct point
    {
        int nxt,to;
        point(){}
        point(const int &nxt,const int &to):nxt(nxt),to(to){}
    }a[N*N];
    inline void link(int x,int y)
    {
        a[++cnt]=(point){head[x],y};head[x]=cnt;
    }
    inline bool check(int x)
    {
        int sum=0;
        for(;x;x-=(x&-x)) ++sum;
        return sum&1;
    }
    inline bool find(int x)
    {
        for(int i=head[x];i;i=a[i].nxt)
        {
            int t=a[i].to;
            if(vis[t]!=tim&&T[t]==tim2)
            {
                vis[t]=tim;
                if(t3[t]!=tim||!f[t]||find(f[t]))
                {
                    f[t]=x;
                    t3[t]=tim;
                    return 1;
                }
            }
        }
        return 0;
    }
    inline int solve()
    {
        int ret=0;
        for(int i=1;i<=m;++i)
        {
            if(T[i]==tim2) ++tim,ret+=find(i);
            else ++ret;
        }
        return m-ret;
    }
    inline void main()
    {
        haku=read();
        while(haku--)
        {
            n=read(),m=read(),k=read();
            for(int i=1;i<=n;++i) ap[i]=read();
            for(int j=1;j<=m;++j) bp[j]=read();
            for(int x,y,i=1;i<=k;++i)
            {
                x=read(),y=read();
                jx[x][y]=1;
            }
            for(int i=1;i<=m;++i)
            {
                if(bp[i]&1)
                {
                    for(int j=1;j<=m;++j)
                    {
                        if(!(bp[j]&1))
                            if(!check(bp[i]|bp[j])) link(i,j);
                    }
                }
            }
            ret=max(ret,solve());
            for(int i=1;i<=n;++i)
            {
                ++tim2;
                for(int j=1;j<=m;++j)
                {
                    if(jx[i][j]) T[j]=tim2;
                }
                ret=max(ret,solve()+1);
            }
            for(int i=1;i<=n;++i)
            {
                if(ap[i]&1)
                for(int j=i+1;j<=n;++j)
                {
                    if(!(ap[j]&1))
                    {
                        ++tim2;
                        for(int k=1;k<=m;++k)
                        {
                            if(jx[i][k]&&jx[j][k]) T[k]=tim2;
                        }
                        ret=max(ret,solve()+2);
                    }
                    
                }
            }
            printf("%d\n",ret);
        }
    }
}
signed main()
{
    red::main();
return 0;
}

Guess you like

Origin www.cnblogs.com/knife-rose/p/12089503.html