zoukankan      html  css  js  c++  java
  • Optimal Milking---poj2112(多重匹配+Floyd+二分)

    题目链接:http://poj.org/problem?id=2112

    题意:K个挤奶器(编号1~K),每个挤奶器每天最多供M头奶牛。共有C头奶牛(编号K+1~K+C)。挤奶器和奶牛间有不同长度的路。

    编写程序,寻找一个方案,安排每头牛到某个挤奶器挤奶,并使得C头奶牛需要走的所有路程的最大路程最小。答案可以用二分来找;

    一对多的二分图的多重匹配。二分图的多重匹配算法的实现类似于匈牙利算法,对于集合x中的元素xi,找到一个与其相连的元素yi后(本题中要满足相连并且距离要小于某个距离),检查匈牙利算法的两个条件是否成立,若yi未被匹配,则将

    xi,yi匹配。否则,如果与yi匹配的元素已经达到上限,那么在所有与yi匹配的元素中选择一个元素,检查是否能找到一条增广路径,如果能,则让出位置,让xi与yi匹配。

    Cows can traverse several paths on the way to their milking machine. 这句话说明了牛可以通过任何路径到达挤奶机,所以要用Floyd更新距离;

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<string>
    #include<stack>
    #include<map>
    using namespace std;
    #define N 1510
    #define INF 0x3f3f3f3f
    #define met(a, b) memset(a, b, sizeof(a))
    
    int G[N][N], vis[N];
    int M, K, C;
    
    struct node
    {
        int k;
        int a[N];
    }Linky[N];
    
    void Floyd()
    {
        for(int k=1; k<=K+C; k++)
        for(int i=1; i<=K+C; i++)
        for(int j=1; j<=K+C; j++)
            G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
    }
    
    bool Find(int u, int Limit)
    {
        for(int i=1; i<=K; i++)
        {
            if( !vis[i] && G[u][i] <= Limit)///距离应在Limit范围之内;
            {
                vis[i] = 1;
                if( Linky[i].k < M )///当与i相连的点的个数小于M个时,直接放进来;
                {
                    Linky[i].a[ Linky[i].k++ ] = u;
                    return true;
                }
                for(int j=0; j<Linky[i].k; j++)///否则就看是否能替换掉其中的一个
                {
                    if(Find(Linky[i].a[j], Limit))
                    {
                        Linky[i].a[j] = u;
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
    bool Hungary(int Limit)
    {
        met(Linky, 0);
        for(int i=K+1; i<=K+C; i++)
        {
            met(vis, 0);
            if( !Find(i, Limit) )///当有一个牛找不到与之相对的挤奶机时,就说明这个Limit不符合条件;
                return false;
        }
        return true;
    }
    
    int solve()
    {
        int L = 0, R = INF, ans = INF;
        while(L <= R)
        {
            int Mid = (L+R)/2;
            if(Hungary(Mid))
            {
                ans = Mid;///不断更新符合条件的答案;
                R = Mid-1;
            }
            else
                L = Mid+1;
        }
        return ans;
    }
    
    int main()
    {
        while(scanf("%d %d %d", &K, &C, &M) != EOF)
        {
            met(G, 0);
    
            for(int i=1; i<=K+C; i++)
            {
                for(int j=1; j<=K+C; j++)
                {
                    scanf("%d", &G[i][j]);
                    if(G[i][j] == 0) G[i][j] = INF;
                }
            }
    
            Floyd();///Floyd求出,各点之间的距离;
    
            int ans = solve();
    
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    union和union all 合并查询
    c#中取整,向上取,向下取
    多个DataSet数据合并
    js未定义判断
    C# 获取时间差状态
    SQL中inner join、outer join和cross join的区别
    朗朗跄跄的受伤,跌跌撞撞的坚强
    IIS7.5 平台.NET无后缀名伪静态实现办法-服务器配置
    检查Android系统版本
    js 实现搜索功能
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5666350.html
Copyright © 2011-2022 走看看