您的位置:首页 > 其它

bzoj1305 [CQOI2009]dance跳舞

2016-04-15 09:35 399 查看
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

先把每个人i拆分成ix和iy两个节点,ix连向喜欢的人,iy连向不喜欢的人,容量为1(比如如果男生i与女生j互相喜欢,则由ix连向jx,如果男生i与女生j互相不喜欢,则由iy连向jy),再将每个男生男生ix连向iy,容量为k;每个女生iy连向ix,容量为k。由源点向每个男生的x节点连上一条边,再由每个女生的x节点向汇点连上一条边,容量均为a。最后从小到大枚举a,计算最大流flow,若发现a*n>flow(不满流),则停止枚举,a-1即为答案。

(粘自hzwer,不要问我为什么,太懒)

#include <bits/stdc++.h>
#define inf 0x7fffffff
#define T 1001
#define N 1010
#define M 100010
using namespace std;
int head
,q
,h
;
int cnt,ans, cur
, mid, mx;
int n,k,mp

;
struct Edge
{
int next, to, v;
}e[M];

inline int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch-'0'; ch = getchar(); }
return x * f;
}

void ins(int u, int v, int w)
{
e[++ cnt].next = head[u];
e[cnt].to = v;
e[cnt].v = w;
head[u] = cnt;
}

void insert(int u, int v, int w)
{
ins(u, v, w);
ins(v, u, 0);
}

int bfs()
{
int t = 0, w = 1;
memset(h, -1, sizeof(h));
h[0] = 0;
q[0] = 0;
while(t != w)
{
int now = q[t ++];
if(t == M) t = 0;
for(int i = head[now]; i; i = e[i].next)
{
int y = e[i].to;
if(h[y] == -1 && e[i].v)
{
h[y] = h[now] + 1;
q[w ++] = y;
if(w == M) w = 0;
}
}
}
if(h[T] == -1) return 0;
else return 1;
}

int dfs(int x, int f)
{
if(x == T) return f;
int used = 0, w;
for(int i = head[x]; i; i = e[i].next)
{
int y = e[i].to;
if(h[y] == h[x] + 1 && e[i].v)
{
w = dfs(y, min(f - used, e[i].v));
e[i].v -= w;
used += w;
//if(e[i].v) cur[x] = i;
e[i ^ 1].v += w;
if(f == used) return used;
}
}
if(used == 0) h[x] = -1;
return used;
}

void dinic()
{
while(bfs())
{
//for(int i = 0; i <= T; i ++)
//a cur[i] = head[i];
ans += dfs(0, inf);
}
}

void Init()
{
n = read();
k = read();
for(int i = 1; i <= n; i ++)
{
char ch[51];
scanf("%s",ch);
for(int j = 1; j <= n; j ++)
if(ch[j - 1] == 'Y')mp[i][j] = 1;
}
}
void build()
{
cnt = 1;
memset(head,0,sizeof(head));
for(int i = 1; i <= n; i ++)insert(0, i, mid);
for(int i = 1; i <= n; i ++)insert(i, i + 500, k);
for(int i = 1; i <= n; i ++)insert(n + i + 500, n + i, k);
for(int i = 1; i <= n; i ++)insert(n + i, T, mid);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
if(mp[i][j]) insert(i, n + j, 1);
else insert(i + 500, n + j + 500, 1);
}
int main()
{
Init();
int l = 0, r = 50;
while(l <= r)
{
mid = (l + r) >> 1;
build();
ans = 0;
dinic();
if(ans >= n * mid) {mx = mid; l = mid + 1;}
else r = mid - 1;
}
printf("%d",mx);
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: