Description
给出一个nn个点的无向完全图,要求给每条边黑白染色,使得图中同色三元环的数量最少,输出最少数量以及染色矩阵
Input
第一行一整数表示用例组数,每组用例输入一整数nn表示点数
Output
输出最少同色三元环数,然后输出一个n×nn×n的染色矩阵AijAij,Aij=1Aij=1表示i,ji,j两点之间的边染黑色,Aij=2Aij=2表示i,ji,j两点之间的边染白色
Sample Input
2
3
6
Sample Output
0
0 1 1
1 0 2
1 2 0
2
0 2 2 1 1 1
2 0 2 1 1 1
2 2 0 1 1 1
1 1 1 0 2 2
1 1 1 2 0 2
1 1 1 2 2 0
Solution
设a[i]a[i]为第ii个点连出去的白色边数量,那么第个点连出去的黑色边数量即为n−1−a[i]n−1−a[i],对于一个不同色三元环,必然是两条边一个颜色另一条边另一个颜色,也即有一个点连出去的两条边是同色的,另外两个点连出去的两条边是异色的,考虑每个点对于不同色三元环的贡献可以得到该图同色三元环个数为C3n−12∑i=1na[i]⋅(n−1−a[i])Cn3−12∑i=1na[i]⋅(n−1−a[i]),为使该值最小,我们要让每一个a[i]⋅(n−1−a[i])a[i]⋅(n−1−a[i])最大,也即a[i]=n−12a[i]=n−12,考虑构造使得每个点连出去的白色边数量为n−12n−12,每次把所有点剩余的白边数量排序,从数量最小的点开始往数量最大的点连边直至数量最小的点的白边连完即可,此时最少同色三元环数量即为C3n−n⋅n−12⋅(n−1−n−12)2Cn3−n⋅n−12⋅(n−1−n−12)2
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=505;
P a[maxn];
int g[maxn][maxn];
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=(i==j?0:1);
for(int i=1;i<=n;i++)a[i].first=(n-1)/2,a[i].second=i;
for(int i=1;i<=n;i++)
{
sort(a+i,a+n+1);
int j=n;
while(a[i].first&&j>i)
{
g[a[i].second][a[j].second]=g[a[j].second][a[i].second]=2;
a[i].first--;
a[j].first--;
j--;
}
}
int ans=n*(n-1)*(n-2)/6-n*((n-1)/2)*(n-1-(n-1)/2)/2;
printf("%d\n",ans);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
printf("%d%c",g[i][j],j==n?'\n':' ');
}
return 0;
}