題目鏈接
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;
}