1305: [CQOI2009]dance跳舞

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 4169  Solved: 1804
[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

 

乍一看以为多重二分图匹配,花了半个小时写出来82分WA了,搜一遍题解才知道是网络流最大流拆点

将所有人拆为两个点,男生为xi,xj,女生为yi,yj

将相互喜欢的人,由xi连向yi,容量为1

将互相不喜欢的人,由xj连向yj,容量为1

将所有男生的xi连向xj,容量为k

将所有女生yj连向yi,容量为k

将源点连向xi,容量为a

  yi连向汇点,容量为a

二分法枚举容量a,计算最大流,若flow<n*a,即无法满流,则停止二分

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 using namespace std;
  6 
  7 const int INF=0x7f7f7f7f;
  8 const int MAXN=400000;
  9 
 10 struct Edge
 11 {
 12     int to,w,next;
 13 }E[MAXN];
 14 int node=1,head[MAXN],dis[MAXN];
 15 int s=0,t=1000;
 16 int n,k,ans;
 17 bool mp[100][100];
 18 
 19 void insert(int u,int v,int w)
 20 {
 21     E[++node]=(Edge){v,w,head[u]};
 22     head[u]=node;
 23     E[++node]=(Edge){u,0,head[v]};
 24     head[v]=node;
 25 }
 26 
 27 bool bfs()
 28 {
 29     memset(dis,-1,sizeof(dis));
 30     queue<int> Q;
 31     Q.push(s);
 32     dis[s]=0;
 33     while(!Q.empty())
 34     {
 35         int q=Q.front();Q.pop();
 36         for(int i=head[q];i;i=E[i].next)
 37             if(E[i].w&&dis[E[i].to]==-1)
 38             {
 39                 Q.push(E[i].to);
 40                 dis[E[i].to]=dis[q]+1;
 41             }
 42     }
 43     return dis[t]!=-1;
 44 }
 45 
 46 int dfs(int x,int flow)
 47 {
 48     if(x==t) return flow;
 49     int w,used=0;
 50     for(int i=head[x];i;i=E[i].next)
 51         if(E[i].w&&dis[E[i].to]==dis[x]+1)
 52         {
 53             w=flow-used;
 54             w=dfs(E[i].to,min(w,E[i].w));
 55             E[i].w-=w;
 56             E[i^1].w+=w;
 57             used+=w;
 58             if(used==flow)return flow;
 59         }
 60     if(!used) dis[x]=-1;
 61     return used;
 62 }
 63 
 64 void dinic()
 65 {
 66     while(bfs()) ans+=dfs(s,INF);
 67 }
 68 
 69 int main()
 70 {
 71     scanf("%d%d",&n,&k);
 72     for(int i=1;i<=n;i++)
 73     {
 74         char ch[100];
 75         scanf("%s",ch);
 76         for(int j=1;j<=n;j++)
 77             if(ch[j-1]=='Y') mp[i][j]=1;
 78     }
 79     int left=0,right=50;
 80     while(left<=right)
 81     {
 82         int mid=(left+right)>>1;
 83         node=1;memset(head,0,sizeof(head));
 84         for(int i=1;i<=n;i++)
 85         {
 86             insert(0,i,mid);
 87             insert(i,i+500,k);
 88             insert(n+i+500,n+i,k);
 89             insert(n+i,t,mid);
 90             for(int j=1;j<=n;j++)
 91                 if(mp[i][j]) insert(i,j+n,1);
 92                 else insert(i+500,j+n+500,1);
 93         }
 94         ans=0;dinic();
 95         if(ans>=n*mid) left=mid+1;
 96         else right=mid-1;
 97     }
 98     printf("%d",left-1);
 99     return 0;
100 }

 

 

 

posted @ 2018-09-30 21:13  InWILL  阅读(137)  评论(0编辑  收藏  举报