zoukankan      html  css  js  c++  java
  • bzoj 1305 dance跳舞

    最大流。

    首先二分答案,问题转化为x首舞曲是否可行。

    考虑建图,对每个人建立三个点,分别表示全体,喜欢和不喜欢。

    源点向每个男生全体点连一条容量为x的边。

    每个男生整体点向喜欢点连一条容量为正无穷的边,向不喜欢点连一条容量为k的边。

    每个男生喜欢点向所有他喜欢的女生的喜欢点连一条容量为一的边,不喜欢点向所有他不喜欢的女生的不喜欢点连一条容量为一的边。

    每个女生喜欢点向整体点连一条容量为正无穷的边,不喜欢点向整体点连一条容量为k的边。

    每个女生整体点向汇点连一条容量为x的边。

    check即为判断最大流是否等于n*x。

    本题中流量的定义为舞曲数,整体点向源汇点的连边保证了每一轮正好配成n对,如某一轮中存在一个女生对应多个男生,最终最大流就会减小。

    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    using namespace std;
    const int dian=305;
    const int bian=40005;
    const int INF=0x3f3f3f3f;
    int n,k,tot;
    int S,T;
    int h[dian],nxt[bian],ver[bian],val[bian],ch[dian];
    char map[55][55];
    void add(int aa,int bb,int cc){
        tot++;ver[tot]=bb;val[tot]=cc;nxt[tot]=h[aa];h[aa]=tot;
        tot++;ver[tot]=aa;val[tot]=0;nxt[tot]=h[bb];h[bb]=tot;
    }
    int bh(int aa,int p,int ok){
        return (aa-1)*3+p+ok*3*n;
    }
    bool tell(){
        memset(ch,-1,sizeof(ch));
        queue<int>q;
        q.push(S);
        ch[S]=0;
        while(!q.empty()){
            int t=q.front();
            q.pop();
            for(int i=h[t];i;i=nxt[i])
                if(ch[ver[i]]==-1&&val[i]){
                    q.push(ver[i]);
                    ch[ver[i]]=ch[t]+1;
                }
        }
        return ch[T]!=-1;
    }
    int zeng(int a,int b){
        if(a==T)
            return b;
        int r=0;
        for(int i=h[a];i&&b>r;i=nxt[i])
            if(ch[ver[i]]==ch[a]+1&&val[i]){
                int t=zeng(ver[i],min(b-r,val[i]));
                val[i]-=t,r+=t,val[i^1]+=t;
            }
        if(!r)
            ch[a]=-1;
        return r;
    }
    int dinic(){
        int r=0,t;
        while(tell())
            while(t=zeng(S,INF))
                r+=t;
        return r;
    }
    bool check(int mid){
        memset(nxt,0,sizeof(nxt));
        memset(h,0,sizeof(h));
        tot=1;
        for(int i=1;i<=n;i++){
            add(S,bh(i,1,0),mid);
            add(bh(i,1,1),T,mid);
            add(bh(i,1,0),bh(i,2,0),INF);
            add(bh(i,1,0),bh(i,3,0),k);
            add(bh(i,2,1),bh(i,1,1),INF);
            add(bh(i,3,1),bh(i,1,1),k);
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(map[i][j]=='Y')
                    add(bh(i,2,0),bh(j,2,1),1);
                else
                    add(bh(i,3,0),bh(j,3,1),1);
            }
        if(dinic()==n*mid)
            return true;
        return false;
    }
    int bin(int l,int r){
        int mid;
        while(l<r){
            mid=(l+r+1)>>1;
            if(check(mid))
                l=mid;
            else
                r=mid-1;
        }
        return l;
    }
    int main(){
        scanf("%d%d",&n,&k);
        S=6*n+1,T=6*n+2;
        for(int i=1;i<=n;i++)
            scanf("%s",map[i]+1);
        printf("%d",bin(0,50));
        return 0;
    }
  • 相关阅读:
    Extjs Google的Suggest的自动提示 从后台取数据
    vue 使用gojs绘制简单的流程图
    网络流24题の详解
    Codeforces Round #587 (Div. 3) F. WiFi(dp+线段树)
    Codeforces Round #588 (Div. 2) E. Kamil and Making a Stream(dfs)
    Spring使用经验之StandardServletMultipartResolver实现文件上传的基本配置
    MySQL + Amoeba 负载均衡、主从备份方案
    SubVersion(SVN)的安装配置使用
    Tomcat Https配置
    Eclipse 常用快捷键清单
  • 原文地址:https://www.cnblogs.com/dugudashen/p/6215992.html
Copyright © 2011-2022 走看看