Codeforces Round #228 (Div. 1) B. Fox and Minimal path

题目链接

http://codeforces.com/contest/388/problem/B

题目大意

给你一个数k
让你构造一个图G, 使1号点到2号点最短路径有k条
输出的图用一个矩阵表示
矩阵有一个两个座标轴, 把矩阵左上角的座标记为(1, 1)座标值分别从左向右、从上到小递增
座标(x, y)为’Y’表示编号为x的点到编号为y的点有一条路, 该路为单向的, 为’N’则表示x与y之间没有路
题目要求构造的图是无向的, 且没有自环, 即Gii = ‘N’
Gij = Gji
题目为特判, 矩阵大小可以自定义

思路

题目要求节点个数不超过1000, 所以矩阵大小最多1000*1000,
直接构造显然是不行的
这时我们就要把路径压缩, 每增添两个节点就能使路径数量*2
1e9的k最多只需用2*30个节点就够了
所以我们可以把k转化为二进制数
比如k = 23(10111)(2^4 + 2^2 + 2^1 + 2^0)
主路
如上图所示, 这样主路就铺好了, 也就是实现了2^4这条路
对于剩下的我们需要铺一条支路
这里写图片描述
对于2^2, 我们把9 连到18, 因为3到9有2^2条路, 且18到15与9到15路程一样, 同理, 把6连到20, 3连到22
这里写图片描述
这样就完成了23条路的构建

代码

#include<bits/stdc++.h>
using namespace std;

bool mp[1005][1005], num[50];

int main()
{
    int k, top = -1, re1 = 4, re2 = 5, re = 3, len = 0;
    scanf("%d", &k);
    while(k)
    {
        num[++top] = (k & 1);
        k >>= 1;
    }
    mp[1][3] = 1, mp[3][1] = 1;
    for(int i=0; i<top; ++i)
    {
        mp[re1][re] = 1, mp[re][re1] = 1;
        mp[re2][re] = 1, mp[re][re2] = 1;
        re += 3;
        mp[re1][re] = 1, mp[re][re1] = 1;
        mp[re2][re] = 1, mp[re][re2] = 1;
        re1 += 3, re2 += 3, len += 2;
    }
    mp[re][2] = 1, mp[2][re] = 1, --len;
    int tmp = re;
    for(int i=0; i<len; ++i)
    {
        mp[tmp][tmp+1] = 1, mp[tmp+1][tmp] = 1;
        ++tmp;
    }
    tmp = re+1;
    for(int i=top-1; i>=0; --i)
    {
        if(num[i])
        {
            int t = re - (top - i) * 3;
            mp[t][tmp] = 1, mp[tmp][t] = 1;
        }
        tmp += 2;
    }
    puts("1000");
    for(int i=1; i<=1000; ++i)
        for(int j=1; j<=1000; ++j)
            j==1000 ? printf("%c\n", mp[i][j] ? 'Y' : 'N') : printf("%c", mp[i][j] ? 'Y' : 'N');
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章