• BZOJ 1305 二分+网络流


    思路:
    建图我根本没有想到啊…….

    (我是不会告诉你我借鉴了一下题解的思路)

    把每个人拆成喜欢的和不喜欢的点

    男 喜欢 向 男 不喜欢 连 边权为k的边

    如果男喜欢女 那么 男喜欢向 女喜欢 连 1

    如果男 不喜欢女 那么 男不喜欢 向 女不喜欢 连1

    男 喜欢 向 男不喜欢 连k

    女 不喜欢 向 女喜欢 连k

    源点 向 男喜欢 连 二分的那个值

    女喜欢 向汇点 连 二分的那个值

    最后判断一下 总流量 是不是等于 n*二分的那个值

    嗯 大概就酱~

    //By SiriusRen
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 10005
    int n,k,ed=6666,answer;
    char a[55][55];
    struct Dinic{
        int first[N],next[N],v[N],w[N],tot,vis[N];
        void add(int x,int y,int z){Add(x,y,z),Add(y,x,0);}
        void Add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
        bool insert(int num){
            memset(first,-1,sizeof(first)),tot=0;
            for(int i=1;i<=n;i++)add(0,i,num);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    if(a[i][j]=='Y')add(i,j+n,1);
                    else add(i+2*n,j+3*n,1);
                }
            for(int i=1;i<=n;i++)add(i,i+2*n,k),add(i+3*n,i+n,k),add(i+n,6666,num);
            return flow()==num*n;
        }
        bool tell(){
            memset(vis,-1,sizeof(vis));vis[0]=0;
            queue<int>q;q.push(0);
            while(!q.empty()){
                int t=q.front();q.pop();
                for(int i=first[t];~i;i=next[i])
                    if(vis[v[i]]==-1&&w[i])
                        vis[v[i]]=vis[t]+1,q.push(v[i]);
            }
            return vis[ed]!=-1;
        }
        int zeng(int x,int y){
            if(x==ed)return y;
            int r=0;
            for(int i=first[x];y>r&&~i;i=next[i])
                if(w[i]&&vis[v[i]]==vis[x]+1){
                    int t=zeng(v[i],min(y-r,w[i]));
                    w[i]-=t,w[i^1]+=t,r+=t;
                }
            if(!y)vis[x]=-1;
            return r;
        }
        int flow(){
            int ans=0,jy;
            while(tell())while(jy=zeng(0,0x3fffff))ans+=jy;
            return ans;
        }
    }dinic;
    int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
        int l=0,r=50;
        while(l<=r){
            int mid=(l+r)>>1;
            if(dinic.insert(mid))answer=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d
    ",answer);
    }

    这里写图片描述

  • 相关阅读:
    记录我的第一次电话面试
    Spring整合Mybatis出现Access denied for user 'Think'@'localhost' (using password: YES)
    Lombok基本使用
    log4j整理
    mybatis常用的配置解析
    Java实现邮件发送
    Java获取UUID
    Java实现文件下载
    Java实现文件上传
    Java跳出多层for循环的4种方式
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532151.html
Copyright © 2020-2023  润新知