CodeForces 1105E

题目链接

std:meet in the middle

首先把所有的点分成两部分,设\(f_i\)为前半部分在点集\(i\)中选出的最大独立集,\(g\)为在后半部分选。这个可以在\(O(2^{m/2})\)的时间复杂度里得到。

然后考虑把答案合起来。在f中是从i这个集合里面选出最大独立集,那么后半部分选的集合一定不能有与i相连的边,那么就把i集合里的点的所有与后半部分相连的点标记成不能选,然后在后半部分选剩下的就好了,这些都已经预处理出来了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#include<map>
#include<string>
#include<iostream>
#define qmin(x,y) (x=min(x,y))
#define qmax(x,y) (x=max(x,y))
using namespace std;

inline char gc() {
//  static char buf[100000],*p1,*p2;
//  return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    return getchar();
}

template<class T>
int read(T &ans) {
    ans=0;char ch=gc();T f=1;
    while(!isdigit(ch)) {
        if(ch==EOF) return -1;
        if(ch=='-') f=-1;
        ch=gc();
    }
    while(isdigit(ch))
        ans=ans*10+ch-'0',ch=gc();
    ans*=f;return 1;
}

template<class T1,class T2>
int read(T1 &a,T2 &b) {
    return read(a)!=EOF&&read(b)!=EOF?2:EOF;
}

template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
    return read(a,b)!=EOF&&read(c)!=EOF?3:EOF;
}

typedef long long ll;
const int Maxn=41;
const int Maxm=1100000;
const int inf=0x3f3f3f3f;

bool mp[Maxn][Maxn],vis[Maxn];
map<string,int> name;
int f[Maxm],g[Maxm],ans,m,x,st[Maxn],top,cnt;
int n;
string s;

signed main() {
//  freopen("test.in","r",stdin);
    read(n,m);memset(mp,1,sizeof(mp));
    for(int i=1;i<=n;i++) {
        read(x);
        if(x==1) {
            for(int j=1;j<=top;j++)
                for(int k=j+1;k<=top;k++)
                    mp[st[j]][st[k]]=mp[st[k]][st[j]]=0;
            top=0;memset(vis,0,sizeof(vis));
        }
        else {
            cin>> s;
            if(!name.count(s)) name[s]=cnt++;
            int x=name[s];
            if(!vis[x]) {
                vis[x]=0;
                st[++top]=x;
            }
        }
    }
    for(int j=1;j<=top;j++)
        for(int k=j+1;k<=top;k++)
            mp[st[j]][st[k]]=mp[st[k]][st[j]]=0;
    int s1=m/2,s2=m-s1;
    for(int i=0;i<s1;i++) f[1<<i]=1;
    for(int i=0;i<(1<<s1);i++)
        for(int j=0;j<s1;j++) if(!(i&(1<<j))) {
            int flag=1;
            for(int k=0;k<s1;k++)
                if(i&(1<<k)) flag&=mp[j][k];
            qmax(f[i|(1<<j)],f[i]+flag);
        }
    for(int i=0;i<s2;i++) g[1<<i]=1;
    for(int i=0;i<(1<<s2);i++)
        for(int j=0;j<s2;j++) if(!(i&(1<<j))) {
            int flag=1;
            for(int k=0;k<s2;k++)
                if(i&(1<<k)) flag&=mp[j+s1][k+s1];
            qmax(g[i|(1<<j)],g[i]+flag);
        }
    for(int i=0;i<(1<<s1);i++) {
        int flag=(1<<s2)-1;
        for(int j=0;j<s1;j++) if(i&(1<<j))
            for(int k=0;k<s2;k++) if(flag&(1<<k)&&!mp[j][k+s1])
                flag^=1<<k;
        qmax(ans,f[i]+g[flag]);
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shanxieng/p/10296984.html