zoukankan      html  css  js  c++  java
  • poj 2112 Optimal Milking(二分+floyd+最大流)

      题目大意就是k个机器和c头牛组成K+C个点,还有个m表示一个机器最多给m头牛服务,然后给你一个(K+C)*(K+C)的矩阵描述了任意2个物体之间的边关系,边权为0表示无边。然后要你在c头牛都能找到机器配对的前提下求c头牛到机器的最远距离的最小值,先把k个机器和c头牛看成是K+C个点,方法就是跑个floyd先求出任意2个点之间的最短距离,然后在二分最远距离的最小值,设low为0,up为100000,这个设的范围包含解在内即可,然后依据mid来建网络流的图,mid表示牛到机器的最远距离,意思是要是i牛到j机器的距离超过了mid,则i牛不能和j机器匹配,即i到j的这条边的容量为0,还有这种多源多汇的最大流还有设个超级源点st,超级汇点et,将et和k个机器连,容量为m(因为每个机器最多服务m头牛),再将st和c头牛连,容量为1,因为1头牛只能匹配一台机器。建完之后就用dinic跑网络了(这也是我第一次用dinic求最大流,没想到一发就过了)。求出来的最大流<c则说明mid太小了,则low=mid+1,否则的话说明最远距离的最小值可能比mid还要小,则up=mid,最后二分搜索结束up就是答案。

    #include<iostream>
    #include<string.h>
    #include<queue>
    #include<stdlib.h>
    using namespace std;
    #define maxn 250
    #define inf 0x3f3f3f3f
    int dis[maxn][maxn],cap[maxn][maxn],depth[maxn];
    int k,c,m;
    int n,st,et;
    int cnt=0;
    void floyd()
    {
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    }
    void build(int maxx)
    {
        for(int i=0;i<=n+1;i++)//正边反边容量清空
            for(int j=i;j<=n+1;j++)
            {
                cap[i][j]=cap[j][i]=0;
            }
        for(int i=k+1;i<=n;i++)//建图
            cap[st][i]=1;
        for(int i=1;i<=k;i++)
            cap[i][et]=m;
        for(int i=k+1;i<=n;i++)
            for(int j=1;j<=k;j++)
            {
                if(dis[i][j]<=maxx)
                {
                    cap[i][j]=1;
                }
    
            }
    }
    bool bfs()//能不能分层等价于该网络流还有没有增广路
    {
        queue<int>q;
        for(int i=st;i<=et;i++)
            depth[i]=0;
        depth[st]=1;
        q.push(st);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int v=st;v<=et;v++)
                if(!depth[v]&&cap[u][v]>0)
                {
                    depth[v]=depth[u]+1;
                    q.push(v);
    
                }
        }
        if(depth[et]==0)
            return false;
        return true;
    }
    int dfs(int u,int f)
    {
        if(u==et)
            return f;
        for(int v=st;v<=et;v++)
        {
            if((depth[v]==depth[u]+1)&&cap[u][v])
            {
                int ff=dfs(v,min(f,cap[u][v]));
                if(ff>0)
                {
                    cap[u][v]-=ff;
                    cap[v][u]+=ff;
                    return ff;
                }
            }
        }
        return 0;
    
    
    }
    int dinic()
    {
        int maxflow=0;
        while(bfs())
        {
            int d;
            while(d=dfs(st,inf))
            {
                //cnt++;
            //cout<<"/第"<<cnt<<"/条增广路  "<<d<<endl;
                maxflow+=d;
            }
        }
        return maxflow;
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        while(cin>>k>>c>>m)
        {
            if(!k&&!c&&!m) break;
            n=k+c;
            st=0;
            et=k+c+1;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    cin>>dis[i][j];
                    if(!dis[i][j])
                        dis[i][j]=inf;
    
                }
            floyd();
            int low,mid,up,flow;
            low=0;
            up=10000;
            while(low<up)
            {
                mid=(low+up)>>1;
                build(mid);
                flow=dinic();
                if(flow<c)
                    low=mid+1;
                else
                    up=mid;
                //cout<<"low:"<<low<<"    up:"<<up;
                //cout<<"  maxflow :"<<flow<<endl;
                //system("pause");
                //cout<<endl;
    
            }
            //cout<<"/maxflow  "<<flow<<endl;
            cout<<up<<endl;
    
    
        }
    }
    

    附上大佬的dinic算法讲解博客

    https://www.cnblogs.com/SYCstudio/p/7260613.html

  • 相关阅读:
    【leetcode】Edit Distance (hard)
    【leetcode】 Interleaving String (hard)
    【leetcode】Regular Expression Matching (hard) ★
    【leetcode】Wildcard Matching(hard) ★ 大神太牛了
    【leetcode】 Longest Valid Parentheses (hard)★
    【leetcode】 Scramble String (hard)★
    【leetcode】Maximal Rectangle (hard)★
    【leetcode】 Unique Binary Search Trees (middle)☆
    【计算机网络】应用层1
    【leetcode】Minimum Path Sum(easy)
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755019.html
Copyright © 2011-2022 走看看