版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niiick/article/details/82898859
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
仅一个数,即舞曲数目的最大值。
题目分析
直接计算似乎不太方便,所以我们尝试二分一个最大值再判断是否可行
把每个点拆成喜欢与不喜欢两个点
即男生喜欢/不喜欢,女生喜欢/不喜欢 共4n个点
设当前二分值为mid
那么由超源向每个男生喜欢连边,容量为mid
由每个女生不喜欢向超汇连边,容量为mid
每个男生由自己的喜欢向自己的不喜欢连边,容量为K
每个女生也同理
对于每对关系
由男生喜欢向女生喜欢 或 男生不喜欢向女生不喜欢 连边,容量为1
若最大流为mid*n,则证明此二分值可行
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int read()
{
int x=0,f=1;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int inf=1e9;
int n,k;
int s,t;
char cp[100][100];
struct node{int v,f,nxt;}E[1000010];
int head[100010],tot=1;
int lev[100010];
int ans,maxf;
void add(int u,int v,int f)
{
E[++tot].nxt=head[u];
E[tot].v=v;
E[tot].f=f;
head[u]=tot;
}
bool bfs()
{
queue<int> q; q.push(s);
memset(lev,-1,sizeof(lev)); lev[s]=0;
while(!q.empty())
{
int u=q.front(); q.pop();
for(int i=head[u];i>0;i=E[i].nxt)
{
int v=E[i].v;
if(lev[v]==-1&&E[i].f)
{
lev[v]=lev[u]+1;
if(v==t) return true;
q.push(v);
}
}
}
return false;
}
int dfs(int u,int cap)
{
if(u==t) return cap;
int flow=cap;
for(int i=head[u];i>0;i=E[i].nxt)
{
int v=E[i].v;
if(lev[v]==lev[u]+1&&E[i].f&&flow)
{
int f=dfs(v,min(flow,E[i].f));
flow-=f;
E[i].f-=f; E[i^1].f+=f;
}
}
return cap-flow;
}
void build(int mid)
{
//i男生喜欢,i+n男生不喜欢,i+2*n女生喜欢,i+3*n女生不喜欢
for(int i=1;i<=n;++i)
{
int num=i+n*3;
add(s,i,mid);add(i,s,0);//超源->男生喜欢
add(num,t,mid);add(t,num,0);//女生不喜欢->超汇
add(i,i+n,k);add(i+n,i,0);//男生/女生喜欢->男生/女生不喜欢
add(num-n,num,k);add(num,num-n,0);
for(int j=0;j<n;j++)
{
int gy=j+1+n*3,gd=j+1+(n<<1);
if(cp[i][j]=='Y')add(i,gy,1),add(gy,i,0);//男生喜欢->女生喜欢
else add(i+n,gd,1),add(gd,i+n,0);//男生不喜欢->女生不喜欢
}
}
}
void init()
{
memset(head,-1,sizeof(head));
tot=1; maxf=0;
}
int main()
{
n=read();k=read(); t=n<<2|1;
for(int i=1;i<=n;++i)
scanf("%s",&cp[i]);
int ll=0,rr=n;
while(ll<rr)
{
int mid=ll+rr>>1;
build(mid);
while(bfs())
maxf+=dfs(s,inf);
if(maxf==mid*n)ans=mid,ll=mid+1;
else rr=mid;
init();
}
build(rr);
while(bfs())
maxf+=dfs(s,inf);
if(maxf==rr*n) cout<<rr;
else cout<<ans;
return 0;
}