题意
(n)个点的有向图,点依次编号为(1)到(n),若(a<b),则点(a)到点(b)有一条有向边。
(a,b)之间的路径定义为从(a)出发,按顺序和边的方向走,最终走到(b)点的边集
彩虹路径定义为路径上的边至少有两种颜色的路径
问一种给边染色的方案,使得所有长度为(k)的路径都是彩虹路径,并且所用的颜色最少
(2le k < n le 1000).
题解
要求即图中不能存在同色的长为(k)的链
考虑把图按点分成(k)块,块与块之间的边用同一种颜色,然后块内的点递归下去做就行.这样能保证同色的链最长是(k-1)
递归(log_k n)次,直到块大小不超过(k)时,块内的最长链长为(k-1),全部染成同一种颜色即可。
比上一题简单多了
// Problem: F. Defender of Childhood Dreams
// Contest: Codeforces - Codeforces Round #749 (Div. 1 + Div. 2, based on Technocup 2022 Elimination Round 1)
// URL: https://codeforces.com/contest/1586/problem/F
// Memory Limit: 512 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1007;
#define ll long long
int n, m, k, tot, ans;
int rd() {
int s = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {s = s * 10 + c - '0'; c = getchar();}
return s * f;
}
int id[maxn][maxn], col[maxn][maxn];
void link(int l1, int r1, int l2, int r2) {
for (int i = l1; i <= r1; i++) {
for (int j = l2; j <= r2; j++) {
col[i][j] = tot;
}
}
}
void sol(int l, int r) {
tot++; //这一次递归用这一种颜色
if (r - l + 1 <= k) {
ans = max(ans, tot);
for (int i = l; i <= r; i++) {
for (int j = l + 1; j <= r; j++) {
col[i][j] = tot;
}
}
tot--;
return;
}
int siz = (r - l + k) / k;
for (int i = l; i <= r; i += siz) {
sol(i, min(r, i + siz - 1));
for (int j = i + siz; j <= r; j += siz) {
link(i, min(r, i + siz - 1), j, min(r, j + siz - 1));
}
}
tot--;
}
int main() {
n = rd(), k = rd();
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
id[i][j] = ++tot;
}
}
tot = 0;
sol(1, n);
printf("%d
", ans);
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
printf("%d ", col[i][j]);
}
}
return 0;
}