効果の件名:
そこ\(A、B \) 2つの設定点、各点少し右に\(A \)セット、エッジ間の2つの点がある満たす(a_iを\ XOR \ a_j \ \ MOD \ 2 = 1 \ )で\(B \)セット、エッジ間の2つの点がある満たす(b_i \ XOR \ b_j \ \ MOD \ 2 = 0 \) または\(b_i \または\ b_j \ ) バイナリの奇数に\ (1 \)
探している\(A、B \)最大グループのセットのサイズを
第一のタイプのデータを:\(| A | B | | \ル200は、ある\ル200が\である)
第二のタイプのデータ:\(| A | \ル10、| B | \ル3000 \)
現時点ではこのアルゴリズムは、最大クリーク問題がある表し\(NPC \)私たちは、直接アドレス指定することはできませんので、問題
しかし、我々多分我々は、図の最大のグループ=最大の独立したセットアップしていることを知っています。
補完的なグラフ最大の独立集合を求めているの設立を考えてみましょう
以下のための\(A \)セット、すべての辺が同じパリティ点を有する間、図に補充された元のパリティ点エッジとの間の異なる存在は、補体の最大独立集合のために、異なるパリティの点との間にエッジが存在しません\ (A \)図2までから選択
ため\(B \)同じパリティの原点との間に縁取らでセット、いくつかのエッジの異なる点のパリティ、図面に記入、パリティの同一点間のエッジ、我々は、分類のための基準を缶パリティはありません図中の二部グラフにアップ。
リアビュー構築\(A \)セットポイント未満、我々は列挙でき\(A \)選択された点の集合、及びそれらの点図完了する構成\(Bを\)セット点マーカー、二部グラフの最大独立集合を実行
多くの場合、少しカード、スタンプの最適化
#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;
}