Codeforces Round #144 (Div. 1) A. Cycles

http://codeforces.com/problemset/problem/232/A

题意:

给你一个数k,用n个点画出k个长度为3的环,然后输出n的个数以及图的矩阵表示,mat[i][j] = 0表示无边 1表示有边。

思路:

如果存在n点的话,则最多能够组合出的长度为3的环有c(n,3)个,当然这些特定的数,不能把k,全部表示出来,我们首先找出C(i,3)<=k的最大的i,然后不断往里面添加点,当我们添加一个点之后,我们可以从已有的图形里面的i个点里面选出2两个与刚加入的节点构成三元环,就这样枚举直到满足k个。

View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <queue>

#include <stack>

#include <set>

#include <map>

#include <string>



#define CL(a,num) memset((a),(num),sizeof(a))

#define iabs(x)  ((x) > 0 ? (x) : -(x))

#define Min(a,b) (a) > (b)? (b):(a)

#define Max(a,b) (a) > (b)? (a):(b)



#define ll long long

#define inf 0x7f7f7f7f

#define MOD 1073741824

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define test puts("<------------------->")

#define maxn 100007

#define M 1000007

#define N 107

using namespace std;

//freopen("data.in","r",stdin);



int mat[N][N];

int main(){

    int k,i,j,ki;

    while (~scanf("%d",&k)){

        CL(mat,0);

       //首先找出小于等于k的最多的节点数i

        for (i = 3; i <= 100; ++i){

            if (i*(i - 1)*(i - 2)/6 > k) break;

        }

        i--;

        k = k - i*(i - 1)*(i -2)/6;

    //更新临界矩阵

        for (j = 1; j <= i; ++j){

            for (ki = 1; ki <= i; ++ki){

                mat[j][ki] = (j != ki)*1;

            }

        }

        //printf(">>>%d %d\n",i,k);

    //逐渐加边,枚举增加的三元环

        while (k > 0){

            for (j = 2; j <= i; ++j){

                if (j*(j - 1)/2 > k) break;

            }

            j--; i++;//i++是新加入的节点

            for (ki = 1; ki <= j; ++ki) mat[i][ki] = mat[ki][i] = 1;

            k -= (j*(j - 1)/2);

        }

        k = i;

        printf("%d\n",k);

        for (i = 1; i <=k ; ++i){

            for (j = 1; j <= k; ++j) printf("%d",mat[i][j]);

            printf("\n");

        }

    }

    return 0;

}

你可能感兴趣的:(codeforces)