Educational Codeforces Round 45 (Rated for Div. 2) D. Graph And Its Complement (构造题)

原题地址:http://codeforces.com/contest/990/problem/D

题意:给出三个数字n,a,b.n表示要构造一个n*n的邻接矩阵,这个矩阵的1表示第i行,第j列有一条边相邻。a表示这个矩阵有a个联通分量,b表示将这个矩阵取反(1的位置表示为0,0的位置表示为1,主对角线的0不变)后的连通分量数。现在询问你能否构造出这样的矩阵,如果能还要输出所构造的矩阵。

思路:我们可以发现通过自己对一些数据的摸索,发现要想构造出这样的矩阵,a和b至少有一个为1.至于为什么你可以自己试几组样例就行了。

下面主要讲讲怎么构造这个矩阵。我们假设a和b中为1的是a。那么我们要想构造出一个矩阵的反矩阵表示的连通分量是b的话,我们必须要使的有b-1个顶点(因为至少有1个联通分量,所以是b-1)与其他的顶点都相连,这样的话,当这个矩阵取反以后,这些与其他顶点都相连的点都会是一个独立的连通分量。

注意1.注意对a是1还是b是1的处理就行了。
注意2.注意(n == 2 || n == 3) && (a == 1 && b == 1)这种情况的特判。

#include <bits/stdc++.h>
using namespace std;
int n, a, b;
const int maxn = 1005;
int mp[maxn][maxn];
int main() {
    scanf("%d%d%d", &n, &a, &b);
    if(a != 1 && b != 1) {
        printf("NO\n");
        return 0;
    }
    if((n == 2 || n == 3) && (a == 1 && b == 1)) {
        printf("NO\n");
        return 0;
    }
    int flag = 1;
    if(b == 1) {
        flag = 0;
        swap(a, b);
    }
    int tmp = b - 1; //要堵的顶点数
    for(int i = 1; i < n; i++) {
        mp[i][i + 1] = mp[i + 1][i] = 1;
    }


    for(int i = 2; i < tmp + 2; i++) {
        for(int j = 1; j <= n; j++) {
            if(i == j) continue;
            mp[i][j] = mp[j][i] = 1;
        }
    }
    printf("YES\n");
    if(flag) {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                printf("%d", mp[i][j]);
            }
            printf("\n");
        }
    } else {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                if(i != j) printf("%d", 1 - mp[i][j]);
                else printf("0");
            }
            printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/80788666