BNU 33693 Problemsetting 枚举+最大流

来源:互联网 发布:淘宝卖家秀大尺度脱毛 编辑:程序博客网 时间:2024/06/04 18:30

传送门

思路:枚举能办的比赛,建边,求最大流,看是否等于需要的题数。

吐槽:BNUOJ数据问题,每行末会有未知字符。。。。。。。。。

代码里有EK有Dinic,可在solve里改下随意调用哪个。

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<map>#include<vector>#include<string>#include<cmath>#define maxn 1<<28using 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 5IOI 3IPSC 2TopCoder 2SEERC 10IOIIPSC TopCoderIOI IPSCIOI IPSCTopCoder SEERC1 1SampleContest 1SampleContest*/