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

    poj 2112 Optimal Milking floyd+二分+最大流
    //poj 2112 Optimal Milking
    
    // floyd + 二分 + 最大流
    
    //题意:第一行给出K,C,M。
    //分别表示挤奶机台数K,奶牛数C,没台挤奶机一天能处理的奶牛数
    //接下去是(K+C) * (K+C) 的矩阵,表示各个点之间的距离
    //0表示不能到达。奶牛走到机器挤奶,求每头牛都要被处理所走的路最少的情况下,
    //每头牛到机器距离中最长的边是多少。记得每台机器都有限制奶牛数
    
    //思路:
    //先用floyd 求出各个点之间的最小路,找出所有路径中最短和最长的边
    //对最长路径进行二分,后建立source连接奶牛,容量为1;
    //建sink,让机器连向sink,容量为机器一天所能处理奶牛的数量;
    //奶牛向机器连边,容量为INF
    
    //注意:
    //奶牛和机器之间的边可以多次使用
    //建的图是有向图,只能从奶牛指向机器有容量INF,机器指向奶牛容量为0
    
    //2 2 1
    //0 0 1 3
    //0 0 2 100
    //1 2 0 0
    //3 100 0 0
    
    #define infile freopen("in.txt", "r", stdin);
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    
    const int INF = 1<<30;
    const int N = 255;
    
    int n, n_mach, n_cow, per_flow, eid;
    int map[N][N], head[N], level[N];
    
    struct EDGE
    {
        int ed, next, cap;
    }edge[2*N*N];
    
    void floyd()    //floyd求各个点之间的最短路
    {
        for(int k = 1; k <= n; ++k)
        {
            for(int i = 1; i <= n; ++i)
            {
                if(i != k)
                {
                    for(int j = 1; j <= n; ++j)
                    {
                        if(j != k && j != i)
                        {
                            if(map[i][j]-map[i][k] > map[k][j])
                            {
                                map[i][j] = map[i][k] + map[k][j];
                            }
                        }
                    }
                }
            }
        }
    }
    
    void add_edge(int st, int ed, int cap)
    {
        edge[eid].ed = ed, edge[eid].cap = cap;
        edge[eid].next = head[st], head[st] = eid++;
    
        edge[eid].ed = st, edge[eid].cap = 0;   //只能从牛到机器,是有向边
        edge[eid].next = head[ed], head[ed] = eid++;
    }
    
    bool bfs()
    {
        memset(level, -1, sizeof(level));
        queue<int>que;
        que.push(0);
        level[0] = 1;
        while(!que.empty())
        {
            int now = que.front();
            que.pop();
            for(int i = head[now]; i != -1; i = edge[i].next)
            {
                int ed = edge[i].ed;
                if(edge[i].cap > 0 && level[ed] == -1)
                {
                    level[ed] = level[now] + 1;
                    que.push(ed);
                }
            }
        }
        if(level[n+1] == -1)
            return false;
        return true;
    }
    
    int dfs(int now, int flow)
    {
        if(now == n+1)
            return flow;
        int tmp = 0;    //tmp为从now流出去的流量
        for(int i = head[now]; i != -1; i = edge[i].next)
        {
            int m = min(edge[i].cap, flow - tmp);
            int ed = edge[i].ed, f;
            if(edge[i].cap > 0 && level[now]+1 == level[ed] && flow > tmp &&
               (f = dfs(ed, m)))
            {
                edge[i].cap -= f;
                edge[i^1].cap += f;
                tmp += f;
            }
        }
        if(tmp == 0)
            level[now] = -1;
        return tmp;
    }
    
    int dinic()
    {
        int flow = 0;
        while(bfs())
            flow += dfs(0, INF);
        return flow;
    }
    
    void binarySearch()
    {
        int high = 0, low = INF;
        for(int i = 1; i <= n; ++i)
        {
            for(int j = i+1; j <= n; ++j)
            {
                low = map[i][j] < low ? map[i][j] : low;
                if(map[i][j] != INF)
                    high = map[i][j] > high ? map[i][j] : high;
            }
        }
        while(low < high)
        {
            eid = 0;
            memset(head, -1, sizeof(head));
            int mid = low + (high-low)/2;
            for(int i = n_mach+1; i <= n; ++i)
            {
                add_edge(0, i, 1);      //source为0,连到每头牛,容量为1
                for(int j = 1; j <= n_mach; ++j)
                {   //注意:这里只能从奶牛走向机器,是单向边
                    if(map[i][j] <= mid)
                    {   //这里奶牛到机器的容量是INF,表示奶牛和机器之间的边可以用不止一次
                        add_edge(i, j, INF);
    //                    printf("%d->%d\n", i, j);
                    }
                }
            }
            for(int i = 1; i <= n_mach; ++i)//sink为n+1,每台机器连向sink,
                add_edge(i, n+1, per_flow); //容量为每台机器一天所能处理的奶牛数
            int flow = dinic();
            if(flow < n_cow)
                low = mid + 1;
            else
                high = mid;
        }
        printf("%d\n", low);
    }
    
    int main()
    {
        //infile
        while(scanf("%d%d%d", &n_mach, &n_cow, &per_flow) != EOF)
        {
            n = n_mach + n_cow;
            for(int i = 1; i <= n; ++i)
            {
                for(int j = 1; j <= n; ++j)
                {
                    scanf("%d", &map[i][j]);
                    map[i][j] = map[i][j] == 0 ? INF : map[i][j];
                }
            }
            floyd();
            binarySearch();
        }
        return 0;
    }
  • 相关阅读:
    XSS练习小游戏和答案参考
    nxlog以syslog方式发送日志
    Hydra—密码爆破神器
    syslog服务器配置笔记
    信息安全工具汇总整理
    nmap使用指南
    Cleaner, more elegant, and harder to recognize (msdn blog)
    Golang 中的坑 一
    Concurrency Is Not Parallelism (Rob pike)
    golang sql database drivers
  • 原文地址:https://www.cnblogs.com/gabo/p/2642255.html
Copyright © 2011-2022 走看看