Codeforces 990D - Graph And Its Complement

传送门:http://codeforces.com/contest/990/problem/D

这是一个构造问题。

构造一张n阶简单无向图G,使得其连通分支个数为a,且其补图的连通分支个数为b。

对于一张n阶简单无向图G,若此图不连通,则其补图是连通的。

证明:

首先,在简单无向图G中,若结点u、v(u≠v)不连通,则在其补图中,u、v必然连通。

将图G=划分为k个连通分支,Gi=i=1,2,...,k。在V中任取两点u、v(u≠v)。

u∈Vi,v∈Vj,且i≠j,则u、v在图G中不连通,则u、v必然在其补图中连通;

u,v∈Vi,则必然存在w∈Vj,且i≠j,使得u、w和v、w在补图中连通。

于是,在题中,a、b中至少有一个为1。

接下来构造连通分支:若一个n阶简单无向图有k(k≥2)个连通分支,则可以构造其连通分支分别为{1},{2},...,{k-1},{k,k+1,...,n}。

参考程序如下:

#include 
using namespace std;

#define MAX_N 1000

bool adj[MAX_N][MAX_N];

int main(void)
{
    int n, a, b;
    cin >> n >> a >> b;
    bool flag = 1;
    if (a != 1 && b != 1) flag = 0;
    if ((n == 2 || n == 3) && (a + b == 2)) flag = 0;
    if (!flag) {
        cout << "NO" << endl;
        return 0;
    }
    cout << "YES" << endl;
    if (b == 1) {
        memset(adj, 0, sizeof(adj));
        for (int i = a; i < n; i++) {
            adj[i - 1][i] = 1;
            adj[i][i - 1] = 1;
        }
    }
    else {
        memset(adj, -1, sizeof(adj));
        for (int i = 0; i < n; i++) adj[i][i] = 0;
        for (int i = b; i < n; i++) {
            adj[i - 1][i] = 0;
            adj[i][i - 1] = 0;
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            putchar(adj[i][j]? '1': '0');
        putchar('\n');
    }
}

 

你可能感兴趣的:(Codeforces 990D - Graph And Its Complement)