码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ 1305】 [CQOI2009]dance跳舞

时间:2015-03-02 09:34:34      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:bzoj   oi   网络流   

1305: [CQOI2009]dance跳舞

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 1586  Solved: 666
[Submit][Status]

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


二分/枚举+网络流


我是用枚举歌曲数为x来做的(枚举每次只要把一些边的流量+1,在原图上继续增广;而二分需要重新构图,重新增广)


我把每个人拆成了3个点a,b,c:a是总点,b是喜欢点,c是不喜欢点。


如果男生i喜欢女生j,则ib,jb连流量为1的边;如果不喜欢则ic,jc连流量为1的边。


对于每个男生的a点与s连流量为x的边,女生的a点与t连流量为x的。


每个人的a与b之间连流量为n的边,a与c之间连流量为k的边。


直接跑最大流,看是否满流,不满流则输出结果。


其实这道题的a点和b点可以合并成一个点的。。


0ms的贪心做法是错误的:

3 0

YYY

YNN

YNN这组数据答案为0,贪心跑出来是1。


#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <queue>
#define M 1005
#define inf 0x3f3f3f3f
using namespace std;
char st[100];
int h[M],flow,cur[M],v[M],d[M],s,t,n,k,tot=1;
struct edge
{
	int from,to,cap,flow,ne;
}E[M*200];
void Addedge(int from,int to,int cap)
{
	E[++tot]=(edge){from,to,cap,0,h[from]};
	h[from]=tot;
	E[++tot]=(edge){to,from,0,0,h[to]};
	h[to]=tot;
}
bool bfs()
{
	queue<int> q;
	q.push(s);
	memset(v,0,sizeof(v));
	v[s]=1,d[s]=0;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		for (int i=h[x];i;i=E[i].ne)
		{
			edge e=E[i];
			if (!v[e.to]&&e.cap>e.flow)
			{
				v[e.to]=1;
				q.push(e.to);
				d[e.to]=d[x]+1;
			}
		}
	}
	return v[t];
}
int dfs(int x,int a)
{
	int flow=0;
	if (x==t||!a) return a;
	for (int &i=cur[x];i;i=E[i].ne)
	{
		edge &e=E[i];
		if (d[e.to]!=d[x]+1) continue;
		int f=dfs(e.to,min(e.cap-e.flow,a));
		if (f>0)
		{
			e.flow+=f;
			E[i^1].flow-=f;
			flow+=f;
			a-=f;
			if (!a) break;
		}
	}
	return flow;
}
void dinic()
{
	while (bfs())
	{
		for (int i=s;i<=t;i++)
			cur[i]=h[i];
		flow+=dfs(s,inf);
	}
}
int main()
{
        scanf("%d%d",&n,&k);
	for (int i=1;i<=n;i++)
	{
		scanf("%s",st);
		for (int k=0;k<n;k++)
		{
			int j=k+1;
			if (st[k]=='Y') Addedge(2*n+i,3*n+j,1);
			else Addedge(4*n+i,5*n+j,1);
		}
	}
	s=0,t=6*n+1;
	for (int i=1;i<=n;i++)
		Addedge(i,4*n+i,k),Addedge(5*n+i,n+i,k),
		Addedge(i,2*n+i,n),Addedge(3*n+i,n+i,n);
	int be=0;
	for (int i=1;i<=n;i++)
	{
		if (i==1) be=tot+1;
		Addedge(s,i,0);
		Addedge(n+i,t,0);
	}
	int ans=0;
	flow=0;
	while (1)
	{
		for (int i=be;i<=tot;i+=2)
			E[i].cap++;
		dinic();
		if (flow==(ans+1)*n) ans++;
		else break;
	}
	printf("%d\n",ans);
	return 0;
}

技术分享

感悟:

一开始建图的+-写错了,wa好多次。。



【BZOJ 1305】 [CQOI2009]dance跳舞

标签:bzoj   oi   网络流   

原文地址:http://blog.csdn.net/regina8023/article/details/44008193

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!