zoukankan      html  css  js  c++  java
  • 2019牛客多校E Androgynos——自补图&&构造

    题目

    给出一个 $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
    ");
                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("
    ");
                }
                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("
    ");
                }
                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("
    ");
                }
                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("
    ");
                }
                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? '
    ':' ');
            }
            else if(n % 4 == 1)
            {
                printf("Yes
    ");
                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
    ");
                }
                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
    ");
                }
                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
    ");
                }
                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
    ");
                }
                for(int i = 1;i <= 2*k;i++)  printf("1");
                for(int i = 2*k+1;i <= 4*k+1;i++)  printf("0");
                printf("
    ");
    
                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
    ", 4*k+1);
            }
            else
            {
                printf("No
    ");
            }
        }
    }
  • 相关阅读:
    详解并发和并行意义
    MoleHill Getting Started AGAL(转)
    解决setInterval计时器不准的问题
    Flash视频播放器开发经验总结
    利用pushState开发无刷页面切换
    用小乐图客抓取人人网照片
    如何在Flash中新窗口打开页面而不被拦截
    响应式开发总结
    用Asroute解决复杂状态切换问题
    对iframe跨域通信的封装
  • 原文地址:https://www.cnblogs.com/lfri/p/11296173.html
Copyright © 2011-2022 走看看