Codeforces 388B Fox and Minimal path 构图

题目大意:

就是现在给出一个k, (1 <= k <= 10^9)

输出一个点数不超过1000的无向图, 所有边权值都是1, 使得从点1到点2的最短路的条数为k条

输出格式为输出一个邻接矩阵


大致思路:

就是构造一个图, 关键就是怎么构造, 首先要求点数不能超过1000, 有一种很容易想到的构造是, 如果现在要有2*10^4条那么在1, 2之间先1连3, 4, 然后3, 4与组(5, 6, 7, 8, 9, 10, 11, 12, 13, 14)中的点互连, 也就是3, 4与这10个点相通, 然后这10个点与下一组10个点相连..重复4个10个点的组最后由2*10*10*10*10条长度为5个路, 连至2, 长度为6

按照这个思想构图, 找到输入的k的最高位, 当最高位是10^i 时, 以长度 i + 1 为最短路长度, 在其他10*10...*10的组的末尾与2相连时中间插入几个点调节最短路长度即可


代码如下:

Result  :  Accepted     Memory  :  1012 KB     Time  :  78 ms

/*
 * Author: Gatevin
 * Created Time:  2015/2/28 14:05:57
 * File Name: Shana.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

lint K;
int bit[20];
vector <int> v;
char M[1010][1010];

int main()
{
    cin>>K;
    if(K == 1)
    {
        printf("2\nNY\nYN\n");
        return 0;
    }
    if(K == 2)
    {
        printf("4\nNNYY\nNNYY\nYYNN\nYYNN\n");
        return 0;
    }
    printf("1000\n");
    for(int i = 1; i <= 1000; i++)
        for(int j = 1; j <= 1000; j++)
            M[i][j] = 'N';
    int len = 0;
    for(int i = 1; i <= 10; i++)
    {
        bit[i] = K % 10;
        K /= 10;
        if(K == 0)
        {
            len = i + 1;
            break;
        }
    }
    int cnt = 3;
    for(int i = 10; i >= 1; i--)
    {
        if(bit[i] == 0) continue;
        for(int j = 0; j < bit[i]; j++)
        {
            v.push_back(cnt + j);
            M[cnt + j][1] = M[1][cnt + j] = 'Y';
        }
        cnt += bit[i];
        for(int k = 1; k < i; k++)
        {
            for(unsigned int j = 0; j < v.size(); j++)
            {
                int now = v[j];
                for(int g = 0; g < 10; g++)
                {
                    M[cnt + g][now] = M[now][cnt + g] = 'Y';
                }
            }
            v.clear();
            for(int j = 0; j < 10; j++)
                v.push_back(j + cnt);
            cnt += 10;
        }
        int nowlen = i;
        if(nowlen + 1 == len)
        {
            for(unsigned int k = 0; k < v.size(); k++)
                M[v[k]][2] = M[2][v[k]] = 'Y';
            v.clear();
            continue;
        }
        else
        {
            for(unsigned int k = 0; k < v.size(); k++)
                M[v[k]][cnt] = M[cnt][v[k]] = 'Y';
            v.clear();
            nowlen++;
            while(nowlen + 1 < len)
            {
                M[cnt + 1][cnt] = M[cnt][cnt + 1] = 'Y';
                nowlen++;
                cnt++;
            }
            M[cnt][2] = M[2][cnt] = 'Y';
            cnt++;
        }
    }
    for(int i = 1; i <= 1000; i++)
    {
        for(int j = 1; j <= 1000; j++)
            printf("%c", M[i][j]);
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值