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;
}

 

posted @ 2012-08-16 14:22  gabo  阅读(208)  评论(0编辑  收藏  举报