Codeforces Round #749 (Div. 1 + Div. 2, based on Technocup 2022 Elimination Round 1) F. Defender of Childhood Dreams

题意

(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;
}
原文地址:https://www.cnblogs.com/YjmStr/p/15434049.html