Bzoj1305 [CQOI2009]dance跳舞

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 2925  Solved: 1221

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

 

网络流 最大流判定+二分+拆点

二分答案,假设可以跳lim首舞曲,那么每个人要有lim个不同的舞伴

每个人拆成三个点n1,n2,n3

从S到每个男生的n1连边,容量为lim,限制此人需要有lim个不同舞伴

从每个男生的n1到n2连边,容量为INF,表示和喜欢的人跳舞的次数没有限制

从每个男生的n1到n3连边,容量为k,表示最多和不喜欢的人跳舞的次数为k

从每个女生的n1到T连边,容量为lim;

从每个女生的n2到n1连边,容量为INF,n3到n1连边,容量为k

从每个男生向每个女生连边,如果喜欢则n2连n2,否则n3连n3,容量为1,表示只和同一个人跳一支舞

跑最大流,如果最大流等于lim*n,说明每个人都找到了lim个舞伴,可行

 

  1 /*by SilverN*/
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<vector>
  8 #include<queue>
  9 using namespace std;
 10 const int INF=1e9;
 11 const int mxn=350;
 12 int read(){
 13     int x=0,f=1;char ch=getchar();
 14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 16     return x*f;
 17 }
 18 struct edge{
 19     int v,nxt,f;
 20 }e[mxn*mxn*20];
 21 int hd[mxn],mct=1;
 22 char mp[60][60];
 23 void add_edge(int u,int v,int f){
 24     e[++mct].v=v;e[mct].nxt=hd[u];e[mct].f=f;hd[u]=mct;return;
 25 }
 26 void insert(int u,int v,int f){
 27     add_edge(u,v,f);
 28     add_edge(v,u,0);
 29     return;
 30 }
 31 int n,m,S,T;
 32 int d[mxn];
 33 bool BFS(){
 34     memset(d,0,sizeof d);
 35     queue<int>q;
 36     d[S]=1;
 37     q.push(S);
 38     while(!q.empty()){
 39         int u=q.front();q.pop();
 40         for(int i=hd[u];i;i=e[i].nxt){
 41             int v=e[i].v;
 42             if(e[i].f && !d[v]){
 43                 d[v]=d[u]+1;
 44                 q.push(v);
 45             }
 46         }
 47     }
 48     return d[T];
 49 }
 50 int DFS(int u,int lim){
 51     if(u==T)return lim;
 52     int f=0,tmp;
 53     for(int i=hd[u];i;i=e[i].nxt){
 54         int v=e[i].v;
 55         if(d[v]==d[u]+1 && e[i].f){
 56             tmp=DFS(v,min(lim,e[i].f));
 57             e[i].f-=tmp;
 58             e[i^1].f+=tmp;
 59             f+=tmp;
 60             lim-=tmp;
 61             if(!lim)return f;
 62         }
 63     }
 64     d[u]=0;
 65     return f;
 66 }
 67 int Dinic(){
 68     int res=0;
 69     while(BFS())res+=DFS(S,INF);
 70     return res;
 71 }
 72 void Build(int lim){
 73     int ed=n+n;
 74     int i,j;
 75     for(i=1;i<=n;i++){//跳舞数量 
 76         insert(S,i,lim);
 77         insert(i,i+ed,INF);
 78         insert(i,i+ed+ed,m);
 79     }
 80     for(i=1;i<=n;i++){
 81         insert(i+n,T,lim);
 82         insert(i+n+ed,i+n,INF);
 83         insert(i+n+ed+ed,i+n,m);
 84     }
 85     for(i=1;i<=n;i++)
 86         for(j=1;j<=n;j++){
 87             if(mp[i][j]=='Y'){
 88                 insert(i+ed,j+n+ed,1);
 89             }
 90             else insert(i+ed+ed,j+n+ed+ed,1);
 91         }
 92     return;
 93 }
 94 void init(){
 95     memset(hd,0,sizeof hd);
 96     mct=1;
 97     return;
 98 }
 99 int ans=0;
100 void solve(){
101     int l=1,r=500;
102     while(l<=r){
103         int mid=(l+r)>>1;
104         init();
105         Build(mid);
106         int res=Dinic();
107         if(res==mid*n){
108             ans=mid;
109             l=mid+1;
110         }else r=mid-1;
111     }
112     return;
113 }
114 int main(){
115     int i,j;
116     n=read();m=read();
117     S=0;T=6*n+1;
118     for(i=1;i<=n;i++)
119         scanf("%s",mp[i]+1);
120     solve();
121     printf("%d\n",ans);
122     return 0;
123 }

 

posted @ 2017-01-06 18:02  SilverNebula  阅读(277)  评论(0编辑  收藏  举报
AmazingCounters.com