思路:枚举能办的比赛,建边,求最大流,看是否等于需要的题数。
吐槽:BNUOJ数据问题,每行末会有未知字符。。。。。。。。。
代码里有EK有Dinic,可在solve里改下随意调用哪个。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<vector>
#include<string>
#include<cmath>
#define maxn 1<<28
using namespace std;
int m,n;
int sum;
int ca;
int sans;
char stt[300];
char aa[10000];
int dis[100];
//int low[100];
int pnum[200];
int fst[100],next[10005],node[10005],c[10005],en,f[10005],pre[100],lu[100];
bool pp[20][60],vis[100],block[100];
void add(int u,int v,int con)
{
next[en]=fst[u];
fst[u]=en;
node[en]=v;
c[en]=con;
en++;
}
void build(int meiju)
{
sum=0;
memset(fst,-1,sizeof(fst));
en=0;
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
if(pp[i][j])
{
add(i,m+j,1);
add(m+j,i,0);
}
}
}
for(int i=1; i<=n; i++)
{
add(m+i,m+n+1,1);
add(m+n+1,m+i,0);
}
for(int i=1; i<=m; i++)
{
if(meiju%2)
{
sum+=pnum[i];
add(0,i,pnum[i]);
add(i,0,0);
}
meiju/=2;
}
}
bool bfs(int s,int t)
{
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
vis[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=fst[u]; i!=-1; i=next[i])
{
int v=node[i];
if(!vis[v]&&f[i]<c[i])
{
vis[v]=1;
pre[v]=u;
lu[v]=i;
if(v==t)return true;
q.push(v);
}
}
}
return false;
}
int ek(int s,int t)
{
memset(f,0,sizeof(f));
int flow=0;
while(bfs(s,t))
{
for(int i=t; i!=s; i=pre[i])
{
int v=lu[i];
f[v]++;
f[v^1]--;
}
flow++;
}
return flow;
}
void lays(int s,int t)
{
int q[3000],front=0,end=0;
for(int i=s; i<=t; i++)dis[i]=maxn;
q[end++]=s;
dis[s]=0;
while(front<end)
{
int u=q[front++];
for(int i=fst[u]; i!=-1; i=next[i])
{
int v=node[i];
if(dis[v]==maxn&&c[i]>f[i])
{
dis[v]=dis[u]+1;
q[end++]=v;
}
}
}
}
int dinic(int s,int t)
{
int flow=0;
memset(f,0,sizeof(f));
memset(block,0,sizeof(block));
//memset(low,0,sizeof(low));
lays(s,t);
int top=s;
while(dis[t]!=maxn)
{
bool flag=false;
//low[s]=maxn;
int i,v;
for(i=fst[top]; i!=-1; i=next[i])
{
v=node[i];
if(c[i]>f[i]&&dis[v]==dis[top]+1&&!block[v])
{
flag=true;
break;
}
}
if(flag)
{
//low[v]=c[i]-f[i];
//if(low[v]>low[top])low[v]=low[top];
pre[v]=top;
top=v;
lu[v]=i;
if(top==t)
{
flow+=1;
int j=top;
while(j!=s)
{
int k=lu[j];
f[k]+=1;
f[k^1]-=1;
j=pre[j];
}
top=s;
//memset(low,0,sizeof(low));
}
}
else
{
block[top]=1;
if(top!=s)top=pre[top];
}
if(block[s])
{
lays(s,t);
memset(block,0,sizeof(block));
}
}
return flow;
}
void solve()
{
int ans=0;
int me=pow(double(2),m);
for(int i=0; i<me; i++)
{
sans=0;
int rrr=i;
while(rrr)
{
if(rrr%2)sans++;
rrr/=2;
}
if(sans<=ans)continue;
build(i);
if(dinic(0,m+n+1)==sum)
{
//cout<<sum<<endl;
ans=sans;
}
}
cout<<"Case #"<<ca++<<": ";
cout<<ans<<endl;
}
int main()
{
ca=1;
while(scanf("%d%d",&m,&n))
{
if(m==0&&n==0)break;
memset(pp,0,sizeof(pp));
string str;
map<string,int>p;
for(int i=1; i<=m; i++)
{
scanf("%s",stt);
str=stt;
p[str]=i;
scanf("%d",&pnum[i]);
getchar();
}
getchar();
for(int i=1; i<=n; i++)
{
gets(aa);
int l=strlen(aa);
str="";
for(int j=0;j<l-1;j++)
{
if(aa[j]==' '&&j!=0)
{
if(aa[j-1]!=' ')
{
pp[p[str]][i]=1;
}
str="";
}
else if(aa[j]!=' ')str+=aa[j];
}
if(str!="")pp[p[str]][i]=1;
}
solve();
}
return 0;
}
/*
4 5
IOI 3
IPSC 2
TopCoder 2
SEERC 10
IOI
IPSC TopCoder
IOI IPSC
IOI IPSC
TopCoder SEERC
1 1
SampleContest 1
SampleContest
*/