首先根据x^y的奇偶将图分成X,Y集合,然后若对任意 x,y ,不满足gcd的条件,既连边,求最大独立集即可 【最大独立集=总权值-最小点覆盖(最大流,最小割)】。
为什么可以这样分成二分图,因为奇数和奇数,或者偶数和偶数异或的时候,二进制第一位一定是0,也就是一定是偶数,题目告诉了我们P一定是偶数,所以它们和P一定至少有一个公约数2,所以它们一定没有边(我们是以不满足条件建边的)。
最大独立集的概念就是,选出权值最大的点,使他们两两都没有边相连。
具体的建图代码就是常规的二分图。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #include<string> #define eps 1e-12 #define INF 0x7fffffff #define maxn 4222 using namespace std; int n,m; int en; int st,ed; //源点和汇点 int dis[maxn] ;//dis[i],表示 到 原点 s 的 层数 int que[999999]; struct edge { int to,c,next; }; edge e[999999]; int head[maxn]; void add(int a,int b,int c) { e[en].to=b; e[en].c=c; e[en].next=head[a]; head[a]=en++; e[en].to=a; e[en].c=0; e[en].next=head[b]; head[b]=en++; } int bfs() { memset(dis,-1,sizeof(dis)); dis[st]=0; int front=0,rear=0; que[rear++]=st; while(front<rear) { int j=que[front++]; for(int k=head[j];k!=-1;k=e[k].next) { int i=e[k].to; if(dis[i]==-1&&e[k].c) { dis[i] = dis[j]+ 1 ; que[rear++]=i; if(i==ed) return true; } } } return false; } int dfs(int x,int mx) { int i,a; if(x==ed) return mx ; int ret=0; for(int k=head[x];k!=-1&&ret<mx;k=e[k].next) { if(e[k].c&&dis[e[k].to]==dis[x]+1) { int dd=dfs(e[k].to,min(e[k].c,mx)); e[k].c-=dd; e[k^1].c+=dd; mx-=dd; ret+=dd; } } if(!ret) dis[x]=-1; return ret; } void init() { en=0; st=n+1; //源 ed=n+2; //汇 memset(head,-1,sizeof(head)); } int gcd(int a,int b) { return a%b==0?b:gcd(b,a%b); } int X[555],topx; int Y[555],topy; int tzf[555]; int val[555]; long long ans; void build() { int x,y,z; topx=topy=0; ans=0; for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); ans+=(x&y); tzf[i]=(x^y); val[i]=(x&y); if((x^y)&1) { add(st,i,x&y); X[topx++]=i; } else { add(i,ed,x&y); Y[topy++]=i; } } for(int i=0;i<topx;i++) { for(int j=0;j<topy;j++) { if(gcd(tzf[X[i]]^tzf[Y[j]],m)<=1) { add(X[i],Y[j],INF); } } } } long long dinic() { int tmp=0; long long maxflow=0; while(bfs()) { while(tmp=dfs(st,INF)) maxflow+=tmp; } return maxflow; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { init(); build(); printf("%lld\n",ans-dinic()); } }