bzoj1305: [CQOI2009]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

 
题解:
将男生i拆为两个点i1,i2,将女生j也拆为j1,j2,如果i和j互相喜欢,则由i1到j1连一条容量为1的边,否则由i2到j2连一条容量为1的边
对于男生i,由i1向i2连一条容量为k的边,对于女生j,由j2向j1连一条容量为k的边
然后二分次数tim,由S向每个男生i1连容量为tim的边,由每个女生j1向T连容量为tim的边,然后如果最大流=tim*n,则这个次数可行
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 250
 7 #define maxm 6000
 8 #define inf 1061109567
 9 using namespace std;
10 char ch;
11 bool ok;
12 void read(int &x){
13     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
14     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
15     if (ok) x=-x;
16 }
17 char g[55][55];
18 int n,k,l,r,m;
19 struct flow{
20     int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm];
21     int dis[maxn],head,tail,list[maxn];
22     bool bo[maxn];
23     void init(){s=0,t=1,tot=1,memset(now,0,sizeof(now));}
24     void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
25     void add(int a,int b,int c){put(a,b,c),put(b,a,0);}
26     bool bfs(){
27         memset(bo,0,sizeof(bo));
28         head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1;
29         while (head<tail){
30             int u=list[++head];
31             for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
32                 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v;
33         }
34         return bo[t];
35     }
36     int dfs(int u,int rest){
37         if (u==t) return rest;
38         int ans=0;
39         for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
40             if (val[p]&&dis[v]==dis[u]+1){
41                 int d=dfs(v,min(rest,val[p]));
42                 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
43             }
44         if (!ans) dis[u]=-1;
45         return ans;
46     }
47     int dinic(){
48         int ans=0;
49         while (bfs()) ans+=dfs(s,inf);
50         return ans;
51     }
52 }f,tmp;
53 bool check(int lim){
54     f=tmp;
55     for (int i=1;i<=n;i++) f.add(f.s,i<<1,lim);
56     for (int i=1;i<=n;i++) f.add((i+n)<<1,f.t,lim);
57     return f.dinic()==lim*n;
58 }
59 int main(){
60     read(n),read(k),f.init();
61     for (int i=1;i<=n;i++) scanf("%s",g[i]+1);
62     for (int i=1;i<=n;i++) f.add(i<<1,(i<<1)+1,k);
63     for (int i=1;i<=n;i++) f.add(((i+n)<<1)+1,(i+n)<<1,k);
64     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++)
65         if (g[i][j]=='Y') f.add(i<<1,(j+n)<<1,1);
66         else f.add((i<<1)+1,((j+n)<<1)+1,1);
67     for (tmp=f,l=0,r=n,m=((l+r)>>1)+1;l<r;m=((l+r)>>1)+1) if (check(m)) l=m; else r=m-1;
68     printf("%d\n",l);
69     return 0;
70 }

 

posted @ 2016-01-18 08:54  chenyushuo  阅读(172)  评论(0编辑  收藏  举报