您的位置:首页 > 其它

bzoj1305: [CQOI2009]dance跳舞

2016-01-18 08:54 417 查看

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

题解:
将男生i拆为两个点i1,i2,将女生j也拆为j1,j2,如果i和j互相喜欢,则由i1到j1连一条容量为1的边,否则由i2到j2连一条容量为1的边
对于男生i,由i1向i2连一条容量为k的边,对于女生j,由j2向j1连一条容量为k的边
然后二分次数tim,由S向每个男生i1连容量为tim的边,由每个女生j1向T连容量为tim的边,然后如果最大流=tim*n,则这个次数可行
code:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 250
#define maxm 6000
#define inf 1061109567
using namespace std;
char ch;
bool ok;
void read(int &x){
for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
if (ok) x=-x;
}
char g[55][55];
int n,k,l,r,m;
struct flow{
int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm];
int dis[maxn],head,tail,list[maxn];
bool bo[maxn];
void init(){s=0,t=1,tot=1,memset(now,0,sizeof(now));}
void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
void add(int a,int b,int c){put(a,b,c),put(b,a,0);}
bool bfs(){
memset(bo,0,sizeof(bo));
head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1;
while (head<tail){
int u=list[++head];
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v;
}
return bo[t];
}
int dfs(int u,int rest){
if (u==t) return rest;
int ans=0;
for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
if (val[p]&&dis[v]==dis[u]+1){
int d=dfs(v,min(rest,val[p]));
val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
}
if (!ans) dis[u]=-1;
return ans;
}
int dinic(){
int ans=0;
while (bfs()) ans+=dfs(s,inf);
return ans;
}
}f,tmp;
bool check(int lim){
f=tmp;
for (int i=1;i<=n;i++) f.add(f.s,i<<1,lim);
for (int i=1;i<=n;i++) f.add((i+n)<<1,f.t,lim);
return f.dinic()==lim*n;
}
int main(){
read(n),read(k),f.init();
for (int i=1;i<=n;i++) scanf("%s",g[i]+1);
for (int i=1;i<=n;i++) f.add(i<<1,(i<<1)+1,k);
for (int i=1;i<=n;i++) f.add(((i+n)<<1)+1,(i+n)<<1,k);
for (int i=1;i<=n;i++) for (int j=1;j<=n;j++)
if (g[i][j]=='Y') f.add(i<<1,(j+n)<<1,1);
else f.add((i<<1)+1,((j+n)<<1)+1,1);
for (tmp=f,l=0,r=n,m=((l+r)>>1)+1;l<r;m=((l+r)>>1)+1) if (check(m)) l=m; else r=m-1;
printf("%d\n",l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: