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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章