zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    122     return 0;
    123 }
  • 相关阅读:
    设计模式详解(一):单例模式
    6大设计原则详解(二)
    6大设计原则详解(一)
    Java线程池的创建详解
    Jquery实现表单动态加减、ajax表单提交
    Java并发编程:浅析几种线程安全模型 [转]
    Java并发之线程状态及Thread常用方法
    Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore[转]
    Java并发之synchronized使用
    Java分布式锁之数据库方式实现
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6257292.html
Copyright © 2011-2022 走看看