Codeforces 388(#228 Div1) B. Fox and Minimal path

問題

無向グラフで頂点1から2への最短パスの総数がちょうどk通りであるような頂点数1000以下のグラフを出力せよ。
答えが複数ある場合はどれを出力してもよい。

制約条件

解の存在は保証されている。

方針

発想としては、kを二進法で書いて、i桁目が1のとき、
2つに分かれて合流する道をi個くっつけた道をスタートからゴールにひく(合計の長さは一定になるように後ろに適当に一本道をくっつける)
というのをやればいいだけ。


これだと頂点が2000くらいになってしまうので、
一番大きい桁だけ分かれて合流するのを繰り返す道を作って、
残りのそれより小さい1の桁は、
(分かれ道の途中に長さの帳尻を合わせて)一本道で途中に合流するとかやればいい。

int k;
string g[1000];

int main(){
	cin >> k;
	int n = 1000;
	rep(i, n) g[i] = string(n, 'N');
	
	int p = 2, pos;
	rep(i, 32) if(k >> i & 1) pos = i;
	{
		int prev = 0;
		rep(j, pos){
			g[prev][p] = g[p][prev] = 'Y'; p++;
			g[prev][p] = g[p][prev] = 'Y'; p++;
			g[p - 1][p] = g[p][p - 1] = 'Y';
			g[p - 2][p] = g[p][p - 2] = 'Y';
			prev = p++;
		}
		rep(j, 2 * (32 - pos)){
			int next = j == 2 * (32 - pos) - 1 ? 1 : p++;
			g[prev][next] = g[next][prev] = 'Y';
			prev = next;
		}
	}
	
	rep(i, pos) if(k >> i & 1){
		int prev = 0;
		int goal = 3 * (pos - i) + 1;
		
		rep(j, 2 * (pos - i)){
			int next = j == 2 * (pos - i) - 1 ? goal : p++;
			g[prev][next] = g[next][prev] = 'Y';
			prev = next;
		}
	}
	cout << n << endl;
	rep(i, n) cout << g[i] << endl;
	return 0;
}