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
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5765192.html