Description
在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着。一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目。
两个国家看成是AB两国,现在是两个国家的描述:
1. A国:每个人都有一个友善值,当两个A国人的友善值a、b,如果a xor b mod 2=1,
那么这两个人都是朋友,否则不是;
2. B国:每个人都有一个友善值,当两个B国人的友善值a、b,如果a xor b mod 2=0
或者 (a or b)化成二进制有奇数个1,那么两个人是朋友,否则不是朋友;
3. A、B两国之间的人也有可能是朋友,数据中将会给出A、B之间“朋友”的情况。
这个题目实际上是要求最大团。如果对最大团的定义不清楚可以点这里。但是这个图是一个一般图,怎么办呢?观察后发现,A国只能选0个人、1个人、2个人(一个奇数一个偶数),而B图的补图又恰好是一个二分图!那就好办了。我们可以枚举A国选了什么人,然后把可选的B国人打上标记,直接跑二分图匹配就好了。记得写初始化啊!
#include
#include
#include
#include
using namespace std;
const int maxn=3010;
int A,B,M,a[maxn],b[maxn],d[maxn],ch[maxn];
bool h[210][maxn];
struct Edge{int y,next;}e[maxn*maxn];
int last[maxn],len=0;
void ins(int x,int y)
{
int t=++len;
e[t].y=y;e[t].next=last[x];last[x]=t;
}
int chw[maxn],match[maxn],T=0,Tc=0;
bool findmatch(int x)
{
if(ch[x]!=Tc)return false;
for(int i=last[x];i!=-1;i=e[i].next)
{
int y=e[i].y;
if(chw[y]!=T&&ch[y]==Tc)
{
chw[y]=T;
if(match[y]==-1||findmatch(match[y]))
{
match[y]=x;
return true;
}
}
}
return false;
}
int count(int x)
{
int re=0;
while(x)
{
re+=(x&1);
x>>=1;
}
return re;
}
int solve()
{
memset(match,-1,sizeof(match));
int re=B;
for(int i=1;i<=B;i++)
if(ch[i]==Tc)
{
T++;
if(findmatch(i))re--;
}
else re--;
return re;
}
int main()
{
memset(ch,0,sizeof(ch));
memset(last,-1,sizeof(last));
scanf("%d%d%d",&A,&B,&M);
for(int i=1;i<=A;i++)scanf("%d",&a[i]);
for(int i=1;i<=B;i++)scanf("%d",&b[i]);
for(int i=1;i<=M;i++)
{
int x,y;
scanf("%d%d",&x,&y);
h[x][y]=true;
}
for(int i=1;i<=B;i++)
if(b[i]&1)
{
for(int j=1;j<=B;j++)
if(!(b[j]&1)&&!(count(b[i]|b[j])&1))ins(i,j);
}
/*选0个A国人*/
int ans=solve();
/*选1个A国人*/
for(int i=1;i<=A;i++)
{
Tc++;
for(int j=1;j<=B;j++)
if(h[i][j])ch[j]=Tc;
ans=max(ans,solve()+1);
}
/*选2个A国人*/
for(int i=1;i<=A;i++)
if(a[i]&1)
{
for(int j=1;j<=A;j++)
if(!(a[j]&1))
{
Tc++;
for(int k=1;k<=B;k++)
if(h[i][k]&&h[j][k])ch[k]=Tc;
ans=max(ans,solve()+2);
}
}
printf("%d",ans);
}