下笔春蚕食叶声。

Horizontal-Vertical Permutation 构造、完全图着色

link

题意

\(n\times n\) 的矩阵,要求 \(\forall k \in[1,n]\) ,第 \(k\) 行和第 \(k\) 列加起来是 \(1...2n-1\)

求出一种可行方案,或输出无解。

题解

(大多是抄的PPT,存个档)

考虑每个位置对哪些目标产生贡献,对角线上的贡献一次,其他的贡献两次。

\(n\) 为奇数,\(2n - 1\) 个数都要贡献奇数次,说明每个数都需要有一个在对角线上,但对角线上只有 \(n\) 个位置,要求 \(2n-1\le n\),所以除了 \(n = 1\) 都必然无解。
\(n\) 为奇数时,考虑把所有的 \(2n-1\) 放在对角线上,剩下的位置对于两个目标点连边,构成了一张完全图(有向图)。
对于完全图的所有边,每个边着一种颜色,共有 \(2n-2\) 种颜色,完全图共有 \(n\) 个点。要求每个点相连的任意两条边颜色不同。
所有的\((i,j)\)\((j,i)\) 很烦 \((i<j)\) ,反正他们永远都一起出现,干脆将他们合为一条边,让\((j,i)=(i,j)+n-1\),变成无向完全图,有 \(n-1\) 种颜色,\(n\) 个点。

循环赛:两两之间都打两场。
转化为偶数大小的循环赛划分(这个不太懂啥意思,大致就是上面说的要求的东西...好像网上也没有看到这样叫的)

边色数
完全图边的着色数最小值

代码

好难写,,

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mkp make_pair
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
int n, ans[510][510];
int change(int x){
	x--; if(x == 0) x = n;
	return x;
}
int change2(int x){
	x++; if(x == n + 1) x = 1;
	return x;
}
int main(){
	//用n-1种颜色对n个点的完全图进行着色 
	scanf("%d", &n);
	if(n == 1){
		puts("Yes\n1"); return 0;
	}
	if(n % 2){
		puts("No"); return 0;
	}
	puts("Yes");
	for(int i = 2; i <= n; i++){
		//标杆指向(1, i),颜色为i-1 
	//	cout<<"calc: "<<i<<endl;
		ans[1][i] = ans[i][1] = i - 1;
		int qwq = i * 2;
		for(int j = 1, k = i, l = i; j <= n / 2 - 1; j++){
			k = change(k); if(k == 1 || k == i) k = change(k);  if(k == 1 || k == i) k = change(k); 
			l = change2(l); if(l == 1 || l == i) l = change2(l);  if(l == 1 || l == i) l = change2(l);
		//	cout<<k<<" "<<l<<endl; 
			ans[k][l] = ans[l][k] = i - 1;
		}
	}
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++){
			if(i > j) ans[i][j] += n - 1;
			if(i == j) ans[i][j] = 2 * n - 1;
			printf("%d%c", ans[i][j], (j < n) ? ' ' : '\n');
		}
	return 0;
}
posted @ 2021-09-13 20:40  ACwisher  阅读(313)  评论(1编辑  收藏  举报