zoukankan      html  css  js  c++  java
  • [CQOI2009]DANCE跳舞

    题目描述

    一次舞会有n个男孩和n个女孩。每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞。每个男孩都不会和同一个女孩跳两首(或更多)舞曲。有一些男孩女孩相互喜欢,而其他相互不喜欢(不会”单向喜欢“)。每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞。给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲?

    输入输出格式

    输入格式:

    第一行包含两个整数n和k。以下n行每行包含n个字符,其中第i行第j个字符为'Y'当且仅当男孩i和女孩j相互喜欢。

    输出格式:

    仅一个数,即舞曲数目的最大值。

    输入输出样例

    输入样例#1:
    3 0
    YYY
    YYY
    YYY
    输出样例#1:
    3

    说明

    N<=50 K<=30

    题解:

    很好想的最大流:

    对于相互喜欢的boy and girl 我们就直接连边 容量为1

    对于不喜欢的,我们要限制和不喜欢的人跳舞的人数不超过k,于是拆点,连 (i,i+n,k)

    boy 和 girl 都要拆点,如果不喜欢,就将boy的辅助点和girl的辅助点相连 容量为1,就可以保证双方都<=k

    然后就是二分答案,S出边和T入边权值改为mid即可

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 using namespace std;
     8 const int SIZE=55,N=205,M=80005,INF=2e9;
     9 int n,k;int map[SIZE][SIZE];char s[SIZE];
    10 int num=1,head[N];
    11 struct Lin{
    12     int next,to,dis;
    13 }a[M];
    14 void init(int x,int y,int z){
    15     a[++num].next=head[x];a[num].to=y;a[num].dis=z;head[x]=num;
    16 }
    17 void addedge(int x,int y,int z){
    18     init(x,y,z);init(y,x,0);
    19 }
    20 int S=0,T,q[N],dep[N];
    21 bool bfs(){
    22     memset(dep,0,sizeof(dep));
    23     int t=0,sum=1,x,u;
    24     q[1]=S;dep[S]=1;
    25     while(t!=sum){
    26         x=q[++t];
    27         for(int i=head[x];i;i=a[i].next){
    28             u=a[i].to;
    29             if(dep[u] || a[i].dis<=0)continue;
    30             dep[u]=dep[x]+1;q[++sum]=u;
    31         }
    32     }
    33     return dep[T];
    34 }
    35 int dfs(int x,int flow){
    36     if(x==T || !flow)return flow;
    37     int u,tot=0,tmp;
    38     for(int i=head[x];i;i=a[i].next){
    39         u=a[i].to;
    40         if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue;
    41         tmp=dfs(u,min(flow,a[i].dis));
    42         a[i].dis-=tmp;a[i^1].dis+=tmp;
    43         tot+=tmp;flow-=tmp;
    44         if(!flow)break;
    45     }
    46     if(!tot)dep[x]=0;
    47     return tot;
    48 }
    49 int maxflow(){
    50     int tot=0,tmp;
    51     while(bfs()){
    52         tmp=dfs(S,INF);
    53         while(tmp)tot+=tmp,tmp=dfs(S,INF);
    54     }
    55     return tot;
    56 }
    57 void Clear(){
    58    num=1;
    59     memset(head,0,sizeof(head));
    60 }
    61 bool check(int lim){
    62     Clear();
    63     for(int i=1;i<=n;i++){
    64         addedge(S,i,lim);addedge(i+n+n,T,lim);
    65         addedge(i,i+n,k);addedge(i+n+n+n,i+n+n,k);
    66     }
    67     for(int i=1;i<=n;i++)
    68         for(int j=1;j<=n;j++){
    69             if(map[i][j])addedge(i,j+n+n,1);
    70             else addedge(i+n,j+n+n+n,1);
    71         }
    72     int ret=maxflow();
    73     return ret==lim*n;
    74 }
    75 void work(){
    76     scanf("%d%d",&n,&k);T=4*n+1;
    77     for(int i=1;i<=n;i++){
    78         scanf("%s",s);
    79         for(int j=1;j<=n;j++)if(s[j-1]=='Y')map[i][j]=true;
    80     }
    81     int l=1,r=n,mid,ans=0;
    82     while(l<=r){
    83         mid=(l+r)>>1;
    84         if(check(mid))ans=mid,l=mid+1;
    85         else r=mid-1;
    86     }
    87     printf("%d
    ",ans);
    88 }
    89 int main()
    90 {
    91     work();
    92     return 0;
    93 }
  • 相关阅读:
    编写高质量代码改善C#程序的157个建议——建议7: 将0值作为枚举的默认值
    编写高质量代码改善C#程序的157个建议——建议6: 区别readonly和const的使用方法
    编写高质量代码改善C#程序的157个建议——建议5: 使用int?来确保值类型也可以为null
    编写高质量代码改善C#程序的157个建议——建议4: TryParse比Parse好
    基于cookie实现用户验证
    页面分页自定义插件
    DOM详习讲解
    HTML标签详细讲解
    Tornado模板配置
    biginteger转Long
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7214569.html
Copyright © 2011-2022 走看看