题解:
显然A国模2的余数相同的没有边,即A国的朋友关系是二分图。那么A国的朋友圈最多2个人。(否则如果有3个人,就有2个人模2的余数相同,做不了朋友)。
B国稍微复杂,因为它本身并不是二分图。但它的补图是二分图,所以可以在补图上跑一发最大独立集,求法为总点数-最大匹配数。
然后枚举A中的点,对于B中和枚举的点都连接的点跑二分图匹配即可。
然后这道题需要注意讨论版:
leoly:对于B类点:偶数点连向奇数点,时间20000+ms;奇数点连向偶数点,时间2000+ms
kac:注意这题实际数据中 只有一组数据 而且没有输入t
话说我一部分memset一部分时间戳到底是要干什么,反正364ms过了
代码:
#include<cstdio>
#include<cstring>
#define maxb 3005
#define maxa 205
#define maxm 9000005
#define max(a,b) ((a)>(b)?(a):(b))
int na,nb,m,mx[maxb],my[maxb],a[maxa],b[maxb],cnt,ok[maxb],vis[maxb],ans,mat;
bool G[maxa][maxb];
struct node { int v; node *nxt; } edge[maxm],*head[maxb],*ncnt;
void addedge(int u,int v)
{
ncnt++;
ncnt->v=v,ncnt->nxt=head[u];
head[u]=ncnt;
}
int dfs(int u)
{
for(node *p=head[u];p;p=p->nxt)
{
int v=p->v;
if(vis[v]==cnt||ok[v]!=cnt) continue;
vis[v]=cnt;
if(!my[v]||dfs(my[v])) { mx[u]=v,my[v]=u; return 1; }
}
return 0;
}
int Get(int x)
{
int cnt=0;
for(;x;x-=x&(-x)) cnt++;
return cnt;
}
int main()
{
scanf("%d%d%d",&na,&nb,&m);
ncnt=&edge[0];
for(int i=1;i<=na;i++) scanf("%d",&a[i]);
for(int i=1;i<=nb;i++) scanf("%d",&b[i]);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u][v]=true;
}
for(int i=1;i<=nb;i++)
for(int j=i+1;j<=nb;j++)
if((b[i]+b[j])%2&&Get(b[i]|b[j])%2==0)
{
if(b[i]%2) addedge(i,j);
else addedge(j,i);
}
cnt++;
for(int i=1;i<=nb;i++) ok[i]=cnt;
for(int i=1;i<=nb;i++)
if(!mx[i]&&b[i]%2) mat+=dfs(i);
ans=nb-mat;
for(int i=1;i<=na;i++)
{
memset(mx,0,sizeof(mx));
memset(my,0,sizeof(my));
cnt++,mat=0;
int cb=0;
for(int j=1;j<=nb;j++)
if(G[i][j]) ok[j]=cnt,cb++;
for(int j=1;j<=nb;j++)
if(ok[j]==cnt&&!mx[j]&&b[j]%2) mat+=dfs(j);
ans=max(ans,1+cb-mat);
for(int j=i+1;j<=na;j++)
if((a[i]+a[j])%2)
{
cnt++,mat=cb=0;
memset(mx,0,sizeof(mx));
memset(my,0,sizeof(my));
for(int k=1;k<=nb;k++)
if(G[i][k]&&G[j][k]) ok[k]=cnt,cb++;
for(int k=1;k<=nb;k++)
if(ok[k]==cnt&&!mx[k]&&b[k]%2) mat+=dfs(k);
ans=max(ans,2+cb-mat);
}
}
printf("%d\n",ans);
}