1. 程式人生 > 其它 >Solution -「CF 1586F」Defender of Childhood Dreams

Solution -「CF 1586F」Defender of Childhood Dreams

\(\mathcal{Description}\)

  Link.

  定義有向圖 \(G=(V,E)\)\(|V|=n\)\(\lang u,v\rang \in E \Leftrightarrow u<v\)。求一個對 \(E\) 的染色 \(f\),使得 \(\not\exist \lang v_1,v_2,\cdots,v_{k+1} \rang, |\{f(v_i,v_{i+1})\mid i\in[1,k]\}|=1\),同時最小化 \(f\) 的值域大小。

  \(2\le k<n\le10^3\)

\(\mathcal{Solution}\)

  設 \(f\)

的值域大小為 \(c\),斷言:\(c\ge\lceil\log_k n\rceil\)

  證明 該結論的等價表述是,若 \(f\) 值域大小為 \(c\),則 \(n\le k^c\)。當 \(c=0\) 時顯然成立。接下來對 \(c\) 進行歸納:

  任取一個 \(f\) 值域大小為 \(c\) 的,被合法染色的圖 \(G\),並任取某種顏色 \(x\),據此將點集 \(V\) 劃分為 \(V_1,V_2,\cdots,V_t\),使得 \(V_i\) 的匯出子圖中不存在顏色為 \(x\) 的邊。這些點集之間的連邊顏色全部為 \(x\),所以 \(t\le k\)。而僅考慮某個 \(V_i\)

的匯出子圖,它至多用 \(c-1\) 中顏色染色,由歸納假設,\(|V_i|\le k^{c-1}\),繼而 \(|V|=\sum |V_i|\le k\cdot 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\n", mxc );
    rep ( i, 1, n ) rep ( j, i + 1, n ) printf( "%d ", ans[i][j] );
    putchar( '\n' );
    return 0;
}