BZOJ1305: [CQOI2009]dance跳舞

来源:互联网 发布:c语言 #define 变量 编辑:程序博客网 时间:2024/05/14 11:30

Description

一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会“单向喜欢”)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?

Input

第一行包含两个整数n和k。以下n行每行包含n个字符,其中第i行第j个字符为'Y'当且仅当男孩i和女孩j相互喜欢。

Output

仅一个数,即舞曲数目的最大值。

Sample Input

3 0
YYY
YYY
YYY

Sample Output

3

HINT

N<=50 K<=30

Source

拆点+二分
把人拆成两个点 S到男孩 女孩到T连二分的答案
然后男女之间喜欢的连1 不喜欢的连1
最后把拆的点连上K
#include<bits/stdc++.h> using namespace std; const int inf=1e9; int ans; int cnt; int head[1010],q[1010],dis[1010]; int n,k,T; struct edge{    int to,nxt;    int flow;}e[500050]; inline void addedge(int x,int y,int fl){    e[++cnt].to=y;    e[cnt].nxt=head[x];    head[x]=cnt;    e[cnt].flow=fl;    e[++cnt].to=x;    e[cnt].nxt=head[y];    head[y]=cnt;    e[cnt].flow=0;} bool mp[1010][1010]; inline bool bfs(){    int ql=0,qr=1;    q[1]=0;    memset(dis,0,sizeof(dis));    dis[0]=1;    while(ql<qr)    {        int x=q[++ql];        for(int i=head[x];i;i=e[i].nxt)        {            int y=e[i].to;            if(e[i].flow&&!dis[y])            {                dis[y]=dis[x]+1;                q[++qr]=y;            }        }    }    if(dis[T]) return true;    return false;}  inline int dfs(int x,int flow){    if(x==T) return flow;    int d,used=0;    for(int i=head[x];i;i=e[i].nxt)    {        int y=e[i].to;        if(e[i].flow&&dis[y]==dis[x]+1)        {            d=dfs(y,min(flow,e[i].flow));            e[i].flow-=d;            e[i^1].flow+=d;            used+=d;            if(used==flow)                return flow;        }    }    if(!used)        dis[x]=-1;    return used;}  inline void dinic(){    while(bfs())        ans+=dfs(0,inf);} inline void build(int x){    cnt=1;    memset(head,0,sizeof(head));    for(int i=1;i<=n;i++)    {        addedge(0,i,x);addedge(i,i+500,k);        addedge(i+n+500,i+n,k);addedge(i+n,T,x);    }    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)            if(mp[i][j]) addedge(i,n+j,1);            else addedge(i+500,n+j+500,1);} int main(){    scanf("%d%d",&n,&k);    T=1001;    for(int i=1;i<=n;i++)    {        char ch[51];        scanf("%s",ch);        for(int j=1;j<=n;j++)            if(ch[j-1]=='Y')                mp[i][j]=1;    }    int mx=0,l=0,r=50;    while(l<=r)    {        int mid=l+r>>1;        build(mid);        ans=0;        dinic();        if(ans>=n*mid)            mx=mid,l=mid+1;        else r=mid-1;    }    cout<<mx;}



0 0