hdu 5823 2016 Multi-University Training Contest 8 color II 解题报告

来源:互联网 发布:你看的我是蓝色的 知乎 编辑:程序博客网 时间:2024/05/21 06:19

题意: 给你一个图,求出每个非空点集染色需要的最少的颜色数,如果有边相连的点颜色不能相同





题解:


一开始口胡了一个貌似正确的搜索就上了,敲完上去WA了,拍下发现这样有问题....


好吧说正解

其实就是要把每个点集分成若干个独立集(独立集就是所有点两两不相连),因为每种颜色染得是一个独立集,要使需要的颜色数最少,就要把点集分成尽量少的独立集,,然后。。。。。。。上状压

f [ id(S) ]表示S这个点集需要的最少的颜色数


然后,2个厉害的东西(可以省不少时间)

1: 枚举一个点集的子集:  

二进制下的 i 是点集S的表示

for( int j=i;j;j=(j-1)&i )


2: unsigned  

这题答案要将每个点集乘一个233^i ,最后Mod 2^32 ,用longlong会超时....

然后很神奇的,unsigned 的范围是0~2^32-1 (这世上怎么会有这么巧的事,故意的一定是故意的.....)

unsigned 输出的时候用 %u




code:

#include<map>#include<set>#include<deque>#include<queue>#include<stack>#include<ctime>#include<cmath>#include<vector>#include<string>#include<bitset>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxn = 22;//const ll Mod = 1ll<<32;struct edge{int y,next;}a[maxn*maxn]; int len,first[maxn];int n,m;unsigned f[1<<maxn];unsigned ans,a0;void insert( int x,int y ){len++;a[len].y = y;a[len].next = first[x]; first[x] = len;}int main(){char st;int t;scanf("%d",&t);while( t-- ){memset( first,0,sizeof first ); len = 0;scanf("%d",&n); getchar();for( int i=1;i<=n;i++ ){for( int j=1;j<=n;j++ ){scanf("%c",&st);if( st == '1' )insert( i,j );}getchar();}memset( f,63,sizeof f );for( int i=1;i<(1<<n);i++ ){bool flag = true;for( int j=0;j<n;j++ )if( i&(1<<j) ){for( int k=first[j+1];k;k=a[k].next )if( i&(1<<(a[k].y-1)) ){flag = false;break;}if( !flag ) break;}if( flag ) f[i] = 1;}for( int i=1;i<(1<<n);i++ )if( f[i] != 1 ){for( int j=i;j;j=(j-1)&i ){if( f[j] == 1 ) f[i] = min( f[i],f[i^j]+1 );}}ans = 0; a0 = 1;for( int i=1;i<(1<<n);i++ ){a0 *= 233;ans += a0*f[i];}printf("%u\n",ans);}return 0;}


0 0