[bzoj1305][网络流]dance跳舞

来源:互联网 发布:js translate 做动画 编辑:程序博客网 时间:2024/05/02 03:07

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

题解

一开始想着二分图匹配。。但是想了想好像要跑k次不行啊
然后旁边大佬就跟我说这题是网络流,一想6666,想建模去。。
对于男生i和女生j,拆成两个点i.x,i.y和j.x,j.y
如果i喜欢j,那么i.x和j.x连边,流量为1因为只能匹配一次
不喜欢的话,那么i.y和j.y连边,流量同上
二分枚举最多能跳舞的次数,源点向i.x连边,流量为次数
j.x向汇点连边,流量同样为次数
i.x和j.x分别向i.y和j.y连边,流量为k
这样跑最大流验证就好了。。
真是神题我却打错了一个符号wa了一发

#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;struct node{    int x,y,c,next,other;}a[210000];int len,last[210000];void ins(int x,int y,int c){    int k1,k2;    len++;k1=len;    a[len].x=x;a[len].y=y;a[len].c=c;    a[len].next=last[x];last[x]=len;    len++;k2=len;    a[len].x=y;a[len].y=x;a[len].c=0;    a[len].next=last[y];last[y]=len;    a[k1].other=k2;a[k2].other=k1;}int h[210000],list[210000];int st,ed,n,k;bool bt_h(){    memset(h,0,sizeof(h));    h[st]=1;list[1]=st;    int head=1,tail=2;    while(head!=tail)    {        int x=list[head];        for(int k=last[x];k;k=a[k].next)        {            int y=a[k].y;            if(a[k].c>0 && h[y]==0)            {                h[y]=h[x]+1;                list[tail++]=y;            }        }        head++;    }    if(h[ed]>0)return true;    return false;}int find_flow(int x,int f){    if(x==ed)return f;    int s=0,t;    for(int k=last[x];k;k=a[k].next)    {        int y=a[k].y;        if(h[y]==h[x]+1 && a[k].c>0 && s<f)        {            s+=(t=find_flow(y,min(a[k].c,f-s)));            a[k].c-=t;a[a[k].other].c+=t;        }    }    if(s==0)h[x]=0;    return s;}char map[60][60];/* boy1 1~n boy2 n+1~n+n girl1 n+n+1~n+n+n girl2 n+n+n+1~n+n+n+n*/bool check(int w){    len=0;memset(last,0,sizeof(last));    st=4*n+1;ed=4*n+2;    for(int i=1;i<=n;i++)    {        ins(st,i,w);ins(i,i+n,k);        for(int j=1;j<=n;j++)        {            if(map[i][j]=='Y')ins(i,j+2*n,1);            else ins(i+n,j+3*n,1);        }    }    for(int i=1;i<=n;i++)ins(i+3*n,i+2*n,k),ins(i+2*n,ed,w);    int q=0;    while(bt_h())q+=find_flow(st,999999999);    if(w*n==q)return true;    return false;}int main(){    scanf("%d%d",&n,&k);    for(int i=1;i<=n;i++)scanf("%s",map[i]+1);    int l=0,r=n,ans;    while(l<=r)    {        int mid=(l+r)/2;        if(check(mid)){ans=mid;l=mid+1;}        else r=mid-1;    }    printf("%d\n",ans);    return 0;}
原创粉丝点击