Live2D

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;
}

posted @ 2021-10-20 21:21  Rainybunny  阅读(96)  评论(1编辑  收藏  举报