(mathcal{Description})
Link.
定义有向图 (G=(V,E)),(|V|=n),(lang u,v ang in E Leftrightarrow u<v)。求一个对 (E) 的染色 (f),使得 ( otexist lang v_1,v_2,cdots,v_{k+1} ang, |{f(v_i,v_{i+1})mid iin[1,k]}|=1),同时最小化 (f) 的值域大小。
(2le k<nle10^3)。
(mathcal{Solution})
设 (f) 的值域大小为 (c),断言:(cgelceillog_k n ceil)。
证明 该结论的等价表述是,若 (f) 值域大小为 (c),则 (nle k^c)。当 (c=0) 时显然成立。接下来对 (c) 进行归纳:
任取一个 (f) 值域大小为 (c) 的,被合法染色的图 (G),并任取某种颜色 (x),据此将点集 (V) 划分为 (V_1,V_2,cdots,V_t),使得 (V_i) 的导出子图中不存在颜色为 (x) 的边。这些点集之间的连边颜色全部为 (x),所以 (tle k)。而仅考虑某个 (V_i) 的导出子图,它至多用 (c-1) 中颜色染色,由归纳假设,(|V_i|le k^{c-1}),继而 (|V|=sum |V_i|le kcdot k^{c-1}=k^c)。 (square)
模仿归纳方法得到构造方法:划分点集,将点集之间的边染色,而后递归处理。复杂度上限为 (mathcal O(n^2))。
(mathcal{Code})
/*+Rainybunny+*/
#include <bits/stdc++.h>
#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
const int MAXN = 1e3;
int n, k, mxc, ans[MAXN + 5][MAXN + 5];
inline void solve( const int l, const int r, const int clr ) {
if ( l == r ) return ;
if ( clr > mxc ) mxc = clr;
int s = ( r - l + k ) / k;
for ( int i = l; i <= r; i += s ) {
solve( i, std::min( i + s - 1, r ), clr + 1 );
rep ( u, l, i - 1 ) rep ( v, i, std::min( i + s - 1, r ) ) {
ans[u][v] = clr;
}
}
}
int main() {
scanf( "%d %d", &n, &k );
solve( 1, n, 1 );
printf( "%d
", mxc );
rep ( i, 1, n ) rep ( j, i + 1, n ) printf( "%d ", ans[i][j] );
putchar( '
' );
return 0;
}