首页 > 代码库 > BZOJ-1305: [CQOI2009]dance跳舞(最大流 增加超级源汇+分裂点+二分 水题)

BZOJ-1305: [CQOI2009]dance跳舞(最大流 增加超级源汇+分裂点+二分 水题)

1305: [CQOI2009]dance跳舞

Time Limit: 5 Sec  Memory Limit: 162 MB

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

 

垃圾网络流1A,增加超级源汇+分裂点+最大流+二分。

男,女各分裂成喜欢yes和不喜欢no两个点

若男女是cp,则每个男yes-->每个女yes 容量1

若男女不是cp,则每个男no-->每个女no 容量1

控制:每个男孩都不会和同一个女孩跳两首(或更多)舞曲。

每个男yes-->自己no 容量k

每个女no-->自己yes 容量k

控制:每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。

最后二分x(暴力枚举ok,数据弱爆了!)

S--->每个男yes 容量x

每个女yes--->T 容量x

若最大流==x*人数(即满流) 则成立。

控制:每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。

ISAP!!!跑的飞快。。。

#include<iostream>#include<fstream>#include<cstdio>#include<algorithm>#include<string>#include<vector>#include<queue>#include<deque>#include<utility>#include<map>#include<set>#include<cmath>#include<cstdlib>#include<ctime>#include<functional>#include<sstream>#include<cstring>#include<bitset>#include<stack>using namespace std;int n,m,s,t,cnt,x,y,z,k,ans;char ss[55][55];struct sdt{    int cap,flow,u,v;}e[200005];int nxt[200005],fir[10005],d[10005],par[10005],num[10005],cur[10005];bool vis[10005];int read(){	int x=0;char c=getchar();	while(c<48||c>57)c=getchar();	while(c>47&&c<58)x*=10,x+=c-48,c=getchar();	return x;}void add(int u,int v,int cp,int fl){	e[++cnt].u=u;e[cnt].v=v;e[cnt].cap=cp;e[cnt].flow=fl;    nxt[cnt]=fir[u];fir[u]=cnt;}void bfs(){    memset(vis,0,sizeof(vis));    memset(d,0,sizeof(d));    queue<int>q;    d[t]=0;    vis[t]=1;    q.push(t);    while(!q.empty())    {        int k=q.front();        q.pop();        for(int i=fir[k];i;i=nxt[i])        {            if(!vis[e[i].v] && e[i].cap==0)            {                vis[e[i].v]=1;                d[e[i].v]=d[k]+1;                q.push(e[i].v);            }        }    }}int agument(){    int p=t;    int ans=2147483647;    while(p!=s)    {        ans=min(ans,e[par[p]].cap-e[par[p]].flow);        p=e[par[p]].u;    }    p=t;    while(p!=s)    {    	e[par[p]].flow+=ans;        e[par[p]^1].flow-=ans;        p=e[par[p]].u;    }    return ans;}int isap(){    memset(num,0,sizeof(num));    int flow=0;    for(int i=1;i<=n;i++)	{		num[d[i]]++;		cur[i]=fir[i];	}    int p=s;    while(d[s]<n)    {        if(p==t)        {            flow+=agument();            p=s;        }        bool ok=0;        for(int i=cur[p];i;i=nxt[i])        {            if(e[i].cap>e[i].flow && d[p]==d[e[i].v]+1)            {                  ok=1;                  par[e[i].v]=i;                  cur[p]=i;                  p=e[i].v;                  break;              }          }        if(!ok)        {            int mn=n-1;            for(int i=fir[p];i;i=nxt[i])            {                if(e[i].cap>e[i].flow)mn=min(mn,d[e[i].v]);            }            if(--num[d[p]]==0)break;            num[d[p]=mn+1]++;            cur[p]=fir[p];            if(p!=s)p=e[par[p]].u;        }    }    return flow;}void build(int yhy){	memset(nxt,0,sizeof(nxt));    memset(fir,0,sizeof(fir));    cnt=1;    for(int i=1;i<=m;i++)    {    	add(1,1+i,yhy,0);    	add(1+i,1,0,0);    	add(1+2*m+i,t,yhy,0);    	add(t,1+2*m+i,0,0);    	for(int j=0;j<m;j++)    	{    		if(ss[i][j]==‘Y‘)    		{    			add(1+i,1+2*m+j+1,1,0);    			add(1+2*m+j+1,i+1,0,0);    		}    		else    		{    			add(1+m+i,1+3*m+j+1,1,0);    			add(1+3*m+j+1,1+i+m,0,0);    		}    	}    	add(1+i,1+m+i,k,0);    	add(1+m+i,1+i,0,0);    	add(1+3*m+i,1+2*m+i,k,0);    	add(1+2*m+i,1+3*m+i,0,0);    }}int main(){    m=read();	k=read();	n=2+4*m;	s=1;	t=2+4*m;		for(int i=1;i<=m;i++)	{		for(int j=0;j<m;j++)		{			cin>>ss[i][j];		}	}	    int l=0,r=m;    while(l<=r)    {    	int mid=(l+r)/2;    	build(mid);    	bfs();	    if(isap()==mid*m)	    {	    	l=mid+1;	    	ans=mid;	    }	    else	    {	    	r=mid-1;	    }    }    printf("%d\n",ans);    return 0;}

  

BZOJ-1305: [CQOI2009]dance跳舞(最大流 增加超级源汇+分裂点+二分 水题)