题目链接:https://ac.nowcoder.com/acm/contest/886/E
题意:给出n,求能否构造一个含n个顶点的简单无向图,且它的补图与它同构。
思路:首先要满足与其补图同构,同构起码要边数相等,所以n(n-1)/4应为整数,即n%4==0/1时存在这样的图。
当n%4==0时:
我们将n个点分成两等份,其中一份构成完全图,另一份构成无边图(没有边),然后在两份之间构造适当数量的边,确保与其补图同构。
当n%4==1时,仅需在上面的基础上将多出的那个点和其中一份相连即可。
AC代码:
#include<cstdio> #include<algorithm> using namespace std; int T,cas,n; int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); if(n%4==2||n%4==3){ printf("Case #%d: No\n",++cas); continue; } else if(n%4==0){ printf("Case #%d: Yes\n",++cas); for(int i=1;i<=n/2;++i){ for(int j=1;j<=n/2;++j){ if(i==j) printf("0"); else printf("1"); } for(int j=1;j<=n/2;++j){ if((i<=n/4&&j<=n/4)||(i>=n/4+1&&j>=n/4+1)) printf("1"); else printf("0"); } printf("\n"); } for(int i=1;i<=n/2;++i){ for(int j=1;j<=n/2;++j){ if((i<=n/4&&j<=n/4)||(i>=n/4+1&&j>=n/4+1)) printf("1"); else printf("0"); } for(int j=1;j<=n/2;++j){ printf("0"); } printf("\n"); } for(int i=1;i<=n;++i){ if(i<=n/2) printf("%d",i+n/2); else printf("%d",n-i+1); if(i!=n) printf(" "); } printf("\n"); } else{ printf("Case #%d: Yes\n",++cas); for(int i=1;i<=n/2;++i){ for(int j=1;j<=n/2;++j){ if(i==j) printf("0"); else printf("1"); } for(int j=1;j<=n/2;++j){ if((i<=n/4&&j<=n/4)||(i>=n/4+1&&j>=n/4+1)) printf("1"); else printf("0"); } printf("1\n"); } for(int i=1;i<=n/2;++i){ for(int j=1;j<=n/2;++j){ if((i<=n/4&&j<=n/4)||(i>=n/4+1&&j>=n/4+1)) printf("1"); else printf("0"); } for(int j=1;j<=n/2;++j){ printf("0"); } printf("0\n"); } for(int i=1;i<=n;++i) if(i<=n/2) printf("1"); else printf("0"); printf("\n"); for(int i=1;i<n;++i){ if(i<=n/2) printf("%d ",i+n/2); else printf("%d ",n-i); } printf("%d\n",n); } } return 0; }