HDU 5823 color II
dp[i]表示i子图的最小染色数目。
dp[i]=min( dp[i], dp[j]+1 ), j是i的子集,并且j图内的点没有边相连。
高效率枚举i子集的方法:for(int j=i;j;j=(j-1)&i) 每一个j都是i的子集。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x; } const int maxn=20; char s[maxn]; int T,n,e[20],f[280000]; bool t[280000]; LL mod=((LL)1<<32); LL POW(LL a,LL b,LL MOD){ LL ret=1; while(b){ if(b&1) ret=(ret*a)%MOD; a=(a*a)%MOD; b>>=1; } return ret; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); memset(e,0,sizeof e); memset(t,0,sizeof t); for(int i=0;i<n;i++) { scanf("%s",s); for(int j=0;s[j];j++) if(s[j]=='1') e[i]=e[i]|(1<<j); } t[0]=1; for(int i=0;i<(1<<n);i++) { if(t[i]==0) continue; int state=i; for(int j=0;j<n;j++) if(i&(1<<j)) state=state|e[j]; for(int j=0;j<n;j++) if(!(state&(1<<j))) t[i|(1<<j)]=1; } f[0]=0; for(int i=1;i<(1<<n);i++) { f[i]=30; for(int j=i;j;j=(j-1)&i) if(t[j]) f[i]=min(f[i],f[i^j]+1); } LL ans=0,P=1; for(int i=0;i<(1<<n);i++) ans=(ans+f[i]*P%mod)%mod, P=P*233%mod; printf("%lld\n",ans); } return 0; }