Grid Coloring
题目描述:
绘制了一个包含 格子的图,他可以用 种颜色,对每一条边进行染色,但有一些限制:
- 每种颜色必须出现相同次数
- 图上不能有单色环
- 每一行和每一列,至少包含 种颜色。
输入描述:
输入包含多个测试用例。 输入的第一行包含一个整数 在接下来的 行中,每行包含两个整数 , , ,描述一个测试用例。
输出描述:
对于每个测试用例,如果没有解决方案,请输出 。否则,输出 行。 对于前 行,每行包含 个整数,表示每条水平线上的边缘颜色;对于后 行,每行包含 个整数,表示每条垂直线上的边缘颜色。
样例输入:
2
2 3
2 5
样例输出:
1 2
3 1
3 2
1 3
2 1
2 3
-1
思路:
首先,我们可以排除三种无解的情况:
然后我们就按照如下方式对图进行标号:
所以我们的标号方式是:自顶向下分别给边按照
到
的顺序标号(如上图),然后我们将颜色
到
按照顺序轮流放到这些边上。
1.对于每一个
的小环,两条纵边必定是相邻的序号,所以染的颜色必然不同
2.对于任意一个
的环,横向边必定有相邻序号,所以染的颜色必然不同,由此又可以证明所有的横向边都是异色的
3.对于任意一个
的环,如果他的横向边长为1,那么他就有相邻的纵向边,如果他的横向边
那么他就有相邻横向边
所以任意一个环和横边均异色。
然后观察上图,发现:任意两条相邻纵向边的序号差必定为
推理到这一步,我们只要证明任意两条相邻纵向边必定异色即可,即
,也就是
证明:
得证。
我还真不信如此复杂的推理得出的代码竟是如此简便…
:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=205;
int a[MAXN][MAXN],b[MAXN][MAXN],T,n,k,t;
int main(){
scanf("%d",&T);
while(T--){
t=0;
scanf("%d%d",&n,&k);
if(n==1|| k==1||(2*n*(n+1))%k){
puts("-1");
continue;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
t=t%k+1;
a[i][j]=t;
}
for(int j=0;j<=n;j++){
t=t%k+1;
b[j][i]=t;
}
}
for(int i=0;i<n;i++){
t=t%k+1;
a[n][i]=t;
}
for(int i=0;i<=n;i++){
for(int j=0;j<n;j++)
printf("%d ",a[i][j]);
puts("");
}
for(int i=0;i<=n;i++){
for(int j=0;j<n;j++)
printf("%d ",b[i][j]);
puts("");
}
}
}