题目
给出一个 $n$,判断是否存在 $n$ 个顶点的自补图,如果存在,输出边和映射。
分析
一个无向图若同构于它的补图,则称该图为自补图。
定理:一个自补图一定存在 $4k$ 或 $4k+1$ 个顶点.
证:
原图的边数+补图的边数=完全图的边数=n(n-1)/2
由于原图与补图同构,所以边数相等,
所以,原图的边数=n(n-1)/4,
边数肯定为整数,所以 4|n 或者 4|(n+1).
现在的问题是如何构造呢?
先考虑 $n=4k$,将其分成两半,
一半连接成完全图,一半为独立的点,
这样边数还不够,再将左上和右下一一相连,右上和左下一一相连。
很容易发现其补图变形一下就跟它一样,然后找一下对应关系。
#include<bits/stdc++.h> using namespace std; int n; int main() { int T, kase=0; scanf("%d", &T); while(T--) { scanf("%d", &n); printf("Case #%d: ", ++kase); if(n % 4 == 0) { printf("Yes\n"); int k = n/4; for(int i = 1; i<= k;i++) { for(int j = 1; j <= 2*k;j++) { if(j == i) printf("0"); else printf("1"); } for(int j = 2*k+1;j <= 3*k;j++) printf("0"); for(int j = 3*k+1;j <= 4*k;j++) printf("1"); printf("\n"); } for(int i = k+1;i <= 2*k;i++) { for(int j = 1; j <= 2*k;j++) { if(j == i) printf("0"); else printf("1"); } for(int j = 2*k+1;j <= 3*k;j++) printf("1"); for(int j = 3*k+1;j <= 4*k;j++) printf("0"); printf("\n"); } for(int i = 2*k+1;i <= 3*k;i++) { for(int j = 1;j <= k;j++) printf("0"); for(int j = k+1;j <= 2*k;j++) printf("1"); for(int j = 2*k+1;j <= 4*k;j++) printf("0"); printf("\n"); } for(int i = 3*k+1;i <= 4*k;i++) { for(int j = 1;j <= k;j++) printf("1"); for(int j = k+1;j <= 2*k;j++) printf("0"); for(int j = 2*k+1;j <= 4*k;j++) printf("0"); printf("\n"); } for(int i = 4*k;i >= 3*k+1;i--) printf("%d ", i); for(int i = 3*k;i >= 2*k+1;i--) printf("%d ", i); for(int i = k;i >= 1;i--) printf("%d ", i); for(int i = 2*k;i >= k+1;i--) printf("%d%c", i, i == k+1? '\n':' '); } else if(n % 4 == 1) { printf("Yes\n"); int k = n/4; for(int i = 1; i<= k;i++) { for(int j = 1; j <= 2*k;j++) { if(j == i) printf("0"); else printf("1"); } for(int j = 2*k+1;j <= 3*k;j++) printf("0"); for(int j = 3*k+1;j <= 4*k;j++) printf("1"); printf("1\n"); } for(int i = k+1;i <= 2*k;i++) { for(int j = 1; j <= 2*k;j++) { if(j == i) printf("0"); else printf("1"); } for(int j = 2*k+1;j <= 3*k;j++) printf("1"); for(int j = 3*k+1;j <= 4*k;j++) printf("0"); printf("1\n"); } for(int i = 2*k+1;i <= 3*k;i++) { for(int j = 1;j <= k;j++) printf("0"); for(int j = k+1;j <= 2*k;j++) printf("1"); for(int j = 2*k+1;j <= 4*k;j++) printf("0"); printf("0\n"); } for(int i = 3*k+1;i <= 4*k;i++) { for(int j = 1;j <= k;j++) printf("1"); for(int j = k+1;j <= 2*k;j++) printf("0"); for(int j = 2*k+1;j <= 4*k;j++) printf("0"); printf("0\n"); } for(int i = 1;i <= 2*k;i++) printf("1"); for(int i = 2*k+1;i <= 4*k+1;i++) printf("0"); printf("\n"); for(int i = 4*k;i >= 3*k+1;i--) printf("%d ", i); for(int i = 3*k;i >= 2*k+1;i--) printf("%d ", i); for(int i = k;i >= 1;i--) printf("%d ", i); for(int i = 2*k;i >= k+1;i--) printf("%d ", i); printf("%d\n", 4*k+1); } else { printf("No\n"); } } }