这题当时搞不出,是问了CrazyBoy的, 超级膜拜。 他的代码超级漂亮
   题意:给出一个无向图n<=12 , 一些节点已经着了颜色,问用k<=12种颜色对图染色的方案数(相邻点不能同色)

   他是用Dp做的,前i种颜色染整个图的方案数
   转移是枚举一个集合染第i种颜色
/*
    2010 Fuzhou Warm up 
    D grap coloring
    Author : CrazyBoy (Jin Bin)
*/


#include
<cstdio>
#include
<cstring>

int color[12];
int G[12];

long long wys[1 << 12] , nwys[1 << 12];

int main()
{
    
int T , n , m , colors;
    scanf(
"%d",&T);
    
while(T--)
    
{
        scanf(
"%d%d%d"&n, &m, &colors);
        memset(G, 
0sizeof(G));
        memset(color, 
0sizeof(color));
        
for(int i = 0 ; i < n ; i++)
        
{
            
int nowc;
            scanf(
"%d"&nowc);
            
if(nowc != 0 )
            
{
                nowc 
--;
                color[nowc] 
|= 1 << i;
            }

        }

        
for(int i = 0; i < m ; i ++)
        
{
            
int a, b ;
            scanf(
"%d%d",&a, &b);
            G[a] 
|= 1 << b;
            G[b] 
|= 1 << a;
        }


        
int MASK = (1 << n) - 1;
        memset(wys, 
0sizeof(*wys) << n );
        wys[
0= 1;
        
for(int i = 0; i < colors; i ++)
        
{
            memset(nwys, 
0sizeof(*nwys) << n );
            
for(int msk = 0; msk <= MASK; msk ++)
            
{
                
if(~msk & color[i])
                    
continue;
                
bool found = false;
                
for(int j = 0; j < n; j ++)
                    
if(msk >> j & 1 && msk & G[j])
                    
{
                        found 
= true;                        
                        
break;
                    }

                
if(found)
                    
continue;
                
int MASK2 = MASK ^ msk;
                
int j = 0;
                
do {
                    nwys[j 
| msk] += wys[j];
                }
while(j = j - MASK2 & MASK2);
            }

            memcpy(wys, nwys, 
sizeof(*wys) << n);
        }

        printf(
"%lld\n",wys[MASK]);
    }

    
return 0;
}