dance跳舞
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
加强数据By dwellings and liyizhen2
又是一道网络流水题……
然而,咱今天晚上做了两道水题,于是就忘记初始化源和汇两次……
思路:
二分解,用网络流判定是否合法。
可以把每个人拆成喜欢的和不喜欢的两个点,然后对于每个男生的喜欢点与源连容量为当前判定解的边,同时向不喜欢点连容量为k的边。
同理,女生的喜欢点对汇连容量为当前判定解的边,同时不喜欢点向喜欢点连k的边。
然后根据喜欢和不喜欢乱连费用为1的边就好~
最大流等于人数乘以解大小即为合法~
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=300;
const int M=1000009;
const int Inf=1e9;
int s,t;
inline int minn(int a,int b){if(a<b)return a;return b;}
inline int maxx(int a,int b){if(a>b)return a;return b;}
namespace koishi
{
int to[M],nxt[M],cap[M],beg[N],tot=1;
int dis[N];
queue<int> q;
inline int init()
{
tot=1;
memset(beg,0,sizeof(beg));
}
inline void adde(int u,int v,int w)
{
to[++tot]=v;
nxt[tot]=beg[u];
cap[tot]=w;
beg[u]=tot;
}
inline void add(int u,int v,int w)
{
adde(u,v,w);
adde(v,u,0);
}
inline bool bfs()
{
while(!q.empty())q.pop();
for(int i=0;i<=t;i++)
dis[i]=-1;
dis[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=beg[u],v;i;i=nxt[i])
if(dis[v=to[i]]==-1 && cap[i])
{
dis[v]=dis[u]+1;
q.push(v);
}
}
return dis[t]!=-1;
}
inline int dfs(int u,int mflow)
{
if(!mflow || u==t)
return mflow;
int cost=0;
for(int i=beg[u],v,f;i;i=nxt[i])
if(dis[v=to[i]]==dis[u]+1 && cap[i])
{
f=dfs(v,minn(cap[i],mflow-cost));
cap[i]-=f;
cap[i^1]+=f;
cost+=f;
if(cost==mflow)
break;
}
if(cost==0)
dis[u]=0;
return cost;
}
inline int dinic()
{
int ans=0;
while(bfs())
ans+=dfs(s,Inf);
return ans;
}
};
using namespace koishi;
int n,k;
char f[109][109];
inline int i1(int x,int cnt)
{
return x+n*cnt;
}
inline int i2(int x,int cnt)
{
return x+n*(cnt+2);
}
inline bool judge(int mval)
{
init();
for(int i=1;i<=n;i++)
{
add(s,i1(i,0),mval);
add(i1(i,0),i1(i,1),k);
add(i2(i,0),t,mval);
add(i2(i,1),i2(i,0),k);
for(int j=1;j<=n;j++)
{
if(f[i][j]!='Y')
add(i1(i,1),i2(j,1),1);
else
add(i1(i,0),i2(j,0),1);
}
}
return dinic()>=mval*n;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%s",f[i]+1);
s=(n<<2)+1,t=s+1;
int l=1,r=n,mid,ans=0;
while(l<=r)
{
mid=l+r>>1;
if(judge(mid))
l=mid+1,ans=mid;
else
r=mid-1;
}
printf("%d\n",ans);
return 0;
}