【bzoj1305】[CQOI2009]dance跳舞

1305: [CQOI2009]dance跳舞

Time Limit: 5 Sec   Memory Limit: 162 MB
Submit: 3822   Solved: 1631
[ Submit][ Status][ Discuss]

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

[ Submit][ Status][ Discuss]



最大流系列


首先基本的建图非常显然:


把s点向男孩i连容量为ans的边,然后男孩i向ai连容量为INF的边,向bi连容量为K的边

其中ai为一个新建点用来连喜欢的边的,bi用来连不喜欢的边的(两者边的容量都为1)


然后女孩也是同理


这样建完后一边枚举ans,一边跑dinic,一旦s向男孩连的边中存在未满流的边,就break掉,输出答案


(貌似二分ans更慢蛤蛤蛤蛤蛤蛤蛤


代码:
#include
#include
#include
#include
using namespace std;

typedef long long LL;

const int maxn = 50 * 10;
const int maxm = maxn * maxn * 10;
const int INF = 2147483647;

struct data{
	int to,cap,flow;
}e[maxm];

vector G[maxn];
int ans,n,m,k,tot,s,t,tote = -1;
int cur[maxn],dis[maxn],Q[maxn];
int lx[maxn],ox[maxn],ly[maxn],oy[maxn];
int id[maxm],now;

inline LL getint()
{
	LL ret = 0;
	char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	while (c >= '0' && c <= '9')
		ret = ret * 10 + c - '0',c = getchar();
	return ret;
}

inline bool bfs()
{
	memset(dis,-1,sizeof(dis));
	memset(cur,0,sizeof(cur));
	int head = 0,tail = 0;
	dis[Q[++tail] = s] = 0;
	while (head < tail)
	{
		int u = Q[++head];
		for (int i = 0; i < G[u].size(); i++)
		{
			data E = e[G[u][i]];
			if (dis[E.to] != -1 || E.flow == E.cap) continue;
			dis[Q[++tail] = E.to] = dis[u] + 1;
		}
	}
	return dis[t] != -1;
}

inline int dinic(int u,int a)
{
	if (u == t || !a) return a;
	int flow = 0;
	for (int &i = cur[u]; i < G[u].size(); i++)
	{
		data &E = e[G[u][i]];
		if (E.flow == E.cap || dis[E.to] != dis[u] + 1) continue;
		int f = dinic(E.to,min(a,E.cap - E.flow));
		if (!f) continue;
		E.flow += f;
		flow += f;
		e[G[u][i] ^ 1].flow -= f;
		a -= f;
		if (!a) break;
	}
	return flow;
}

inline void add(int u,int v,int cap)
{
	e[++tote] = (data){v,cap,0};
	G[u].push_back(tote);
	e[++tote] = (data){u,cap,cap};
	G[v].push_back(tote);
}

inline char getcom()
{
	char c = getchar();
	while (c != 'Y' && c != 'N') c = getchar();
	return c;
}

int main()
{
	n = getint(); k = getint();
	s = ++tot; t = ++tot;
	for (int i = 1; i <= n; i++)
	{
		int tmp = ++tot;
		add(s,tmp,0);
		id[++now] = tote - 1;
		add(tmp,lx[i] = ++tot,k);
		add(tmp,ox[i] = ++tot,INF);
		
		tmp = ++tot;
		add(tmp,t,0);
		id[++now] = tote - 1;
		add(ly[i] = ++tot,tmp,k);
		add(oy[i] = ++tot,tmp,INF);
	}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			char c = getcom();
			if (c == 'Y') add(ox[i],oy[j],1);
			else add(lx[i],ly[j],1);
		}
	for (int i = 1; i <= n + 1; i++)
	{
		for (int j = 1; j <= now; j++)
		{
			e[id[j]].cap++;
			e[id[j] ^ 1].cap++;
			e[id[j] ^ 1].flow++;
		}
		int ans = 0;
		while (bfs()) 
			ans += dinic(s,INF);
		int flag = 0;
		for (int j = 1; j <= now; j++)
			if (e[id[j]].flow < e[id[j]].cap)
				flag = 1;
		if (flag) 
		{
			printf("%d",i - 1);
			break;
		}
	}
	return 0;
}



你可能感兴趣的:(网络流)