In graph theory, graph colouring is a special case of graph labelling.
It is an assignment of labels traditionally called colours to edges of a graph.
Here we consider the simplest form.
Given an undirected simple complete graph G with n nodes, this problem asks
about a black-and-white edge-colouring of G, which contains the smallest total number of pure-coloured triangles.
A pure-coloured triangle in G is a set of three different nodes with three same-coloured edges between them.
Input Format
The input has several test cases and the first line provides the total number of test cases.
For each test case, a line with an integer n (n≤500) indicates that the given graph G is an undirected simple complete graph with n nodes.
Output Format
For each test case, output n+1 lines.
The first line contains the smallest number of pure-coloured triangles.
The following n lines describes an adjacent matrix A=(aij) of graph G.
The answer may not be unique and you can output anyone.
If the edge between i and j is white, aij and aji should be 1.
If the edge between i and j is black, aij and aji should be 2.
Elements of the main diagonal should be 0.
样例输入
2 3 6
样例输出
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
题目来源
题目大意:
让我们构造出一个完全无向图,使得其中只包含1或者2这两种颜色,并且使得构造出来的图包含的颜色相同的边的三元环数量最少。
输出三元环的个数,并且输出图的形状。
思路(思路源自:http://blog.csdn.net/yasola/article/details/77916937):
①我们根据补集思想,我们知道,Ans=C(n,3)-Σd[i]*(n-1-d[i]);这里d【i】表示点i具有颜色1的边的条数。
②那么我们希望Ans小的话,那就要最大化Σd[i]*(n-1-d[i]),对于每个i,结果都是独立的,所以我们就是希望最大化d[i]*(n-1-d[i]).根据小学数学知识不难得知,正方形的面积最大,所以我们尽可能的将其平均分配即可,使得d【i】=(n-1)/2.那么对于独立的每个部分的贡献就是(n-1)/2*(n-1)/2;
③然后我们每次连边随便sort做一做就行了。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int ans[505][505];
struct node
{
int u,need;
}a[505];
int cmp(node a,node b)
{
return a.need<b.need;
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
{
a[i].u=i;
a[i].need=(n-1)/2;
for(int j=1;j<=n;j++)
{
ans[i][j]=2;
}
}
while(1)
{
int pos=-1;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(a[i].need>0)
{
pos=i;
break;
}
}
if(pos==-1)break;
int flag=0;
for(int j=n;j>pos;j--)
{
if(a[j].need>0&&a[pos].need>0)
{
flag=1;
a[j].need-=1;
a[pos].need-=1;
ans[a[pos].u][a[j].u]=1;
ans[a[j].u][a[pos].u]=1;
}
}
if(flag==0)break;
}
int anss=n*(n-1)*(n-2)/6;
anss-=n*((n-1)*(n-1)/4)/2;
printf("%d\n",anss);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)ans[i][j]=0;
if(j>1)printf(" ");
printf("%d",ans[i][j]);
}
printf("\n");
}
}
}