Problem Description
You are given an undirected graph with n vertices numbered 0 through n-1.
Obviously, the vertices have 2^n - 1 non-empty subsets. For a non-empty subset S, we define a proper coloring of S is a way to assign each vertex in S a color, so that no two vertices in S with the same color are directly connected by an edge. Assume we've used k different kinds of colors in a proper coloring. We define the chromatic number of subset S is the minimum possible k among all the proper colorings of S.
Now your task is to compute the chromatic number of every non-empty subset of the n vertices.
Input
First line contains an integer t. Then t testcases follow.
In each testcase: First line contains an integer n. Next n lines each contains a string consisting of '0' and '1'. For 0<=i<=n-1 and 0<=j<=n-1, if the j-th character of the i-th line is '1', then vertices i and j are directly connected by an edge, otherwise they are not directly connected.
The i-th character of the i-th line is always '0'. The i-th character of the j-th line is always the same as the j-th character of the i-th line.
For all testcases, 1<=n<=18. There are no more than 100 testcases with 1<=n<=10, no more than 3 testcases with 11<=n<=15, and no more than 2 testcases with 16<=n<=18.
Output
For each testcase, only print an integer as your answer in a line.
This integer is determined as follows:
We define the identity number of a subset S is id(S)=∑v∈S2v. Let the chromatic number of S be fid(S).
You need to output ∑1<=id(S)<=2n−1fid(S)×233id(S)mod232.
Sample Input
2
4
0110
1010
1101
0010
4
0111
1010
1101
1010
Sample Output
1022423354
2538351020
Hint
For the first test case, ans[1..15]= {1, 1, 2, 1, 2, 2, 3, 1, 1, 1, 2, 2, 2, 2, 3}
题意:给一个N*N的矩阵,a[i][j]=1表示点i与点j相连。对于N个点有2^n-1个子集,相连的点不能同色,问对于每个子集最少需要多少颜色。
ans[i]表示i(二进制)状态下的最少颜色数,输出结果∑ans[i]×233^i mod 2^32.
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
using namespace std;
typedef unsigned int ui;
ui p233[300005];
int temp[300005][20];
int col[300005][20]; //记录i状态xia
void init() //预处理233的幂次,以及每个状态temp
{
memset(p233,0,sizeof(p233));
memset(temp,0,sizeof(temp));
p233[0]=1;
for (int i=1;i<=(1<<18);i++)
p233[i]=p233[i-1]*(unsigned int)233;
for(int i=0;i<=300000;i++)
{
int x=i;
int cnt=0;
while(x>0)
{
temp[i][cnt]=x%2;
x/=2;
cnt++;
}
}
}
char ss[20][20];
int maps[20][20]; //存图
ui dp[300005]; //表示i状态时最少需要多少种颜色
int vis[20];
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
memset(maps,0,sizeof(maps));
memset(col,0,sizeof(col));
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",ss[i]);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(ss[i][j]=='0') maps[i][j]=0;
else maps[i][j]=1;
}
}
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++) //当状态中只有一个点的时候
{
col[1<<i][i]=1; //这个点颜色标为1
dp[i]=1; //这个状态需要一种颜色
}
for(int i=1;i<(1<<n);i++)
{
int color=n+1;
int pos=n+1;
for(int j=0;j<n;j++)
{
if(temp[i][j]==1)
{
memset(vis,0,sizeof(vis));
for(int k=0;k<n;k++)
{
if(maps[j][k]==1)
{
vis[col[i^(1<<j)][k]]=1; //统计新增加的这个点与哪些颜色相连
}
}
for(int k=1;k<=n;k++)
{
if(vis[k]==0)
{
if(color>k)
{
color=k; //color表示最小的不相连的颜色
pos=j;
}
break;
}
}
}
}
for(int j=0;j<n;j++)
{
if(temp[i][j]==1)
{
col[i][j]=col[i^(1<<pos)][j];
}
}
col[i][pos]=color;
if(color>dp[i^(1<<pos)]) dp[i]=dp[i^(1<<pos)]+1; //如果与所有的颜色都相连,就要新增一种颜色
else dp[i]=dp[i^(1<<pos)];
}
ui res=0;
for(int i=1;i<(1<<n);i++)
{
res=res+p233[i]*dp[i]; //unsigned int自动取膜
}
printf("%u\n",res);
}
return 0;
}