POJ2112 Optimal Milking

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

二.题目大意:给出一个挤奶机与奶牛之间的图,挤奶机每天可以挤的奶牛头数是一定的。求在保证每头牛都能挤奶的情况下,求一个方案,其中奶牛要走到挤奶机前的最大路径最小。

三.思路:这题好玩,怎么想呢。

1.每头奶牛走到挤奶机的路径要尽可能小,但是奶牛走到挤奶机的路不是一步到达的,因此我们可以想到先用Floyd求出各个实体的最短路径。

2.然后,很自然的想法就是删除最大的边,求一次。再删除较大的边,再求一次。直到删到一条不能再删的边,就得到了答案。但是再深入想一下,就会觉得直接二分搜索就可以了。但是怎么求呢?

3.要让每头牛走到挤奶机面前,由于是在最大流里面看到它的,于是我们努力用最大流来想,强行最大流,自己建一个源点和汇点,将源点与每头牛之间的容量存为1,每个挤奶机与汇点之间的容量为M,牛跟它可到达的挤奶机之间距离为1。这样求一个最大流,如果求出的最大流为C,也就是奶牛数,说明可以让所有奶牛挤奶,因为所有奶牛都经过中间的挤奶点到达了汇点,而且每个挤奶点接收的流量不会超过M。

四.代码:

#include 
#include 
#include 
#include 
#include 

using namespace std;

const int INF = 0x3f3f3f3f,
          MAX_SIZE = 256;

int capacity[MAX_SIZE][MAX_SIZE],
    graph[MAX_SIZE][MAX_SIZE], K, C, M, dist[MAX_SIZE];

void Floyd()
{
    int i, j, k;
    for(k = 1; k <= K + C; k++)
        for(i = 1; i <= K + C; i++)
        for(j = 1; j <= K + C; j++)
        graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]);
}

int maxEdge()
{
    int i, j, res = -1;
    for(i = 1; i <= K + C; i++)
        for(j = 1; j <= K + C; j++)
        if(graph[i][j] < INF)
            res = max(res, graph[i][j]);
    return res;
}

bool BFS()
{
    memset(dist, -1, sizeof(dist));
    int i, cur;
    queue  que;
    que.push(0);
    dist[0] = 0;
    while(!que.empty()){
        cur = que.front();
        que.pop();
        for(i = 0; i <= K+C+1; i++)
            if(-1 == dist[i] && capacity[cur][i] > 0){
                que.push(i);
                dist[i] = dist[cur] + 1;
            }
    }

    if(-1 == dist[K+C+1])
        return false;
    return true;
}

int DFS(int s, int minFlow)
{
    int i, temp, save;

    if(s == K+C+1)
        return minFlow;

    save = minFlow;
    for(i = 0; i <= K+C+1; i++)
        if(capacity[s][i] > 0 && dist[i] == dist[s] + 1){
                temp = DFS(i, min(minFlow, capacity[s][i]));
                capacity[s][i] -= temp;
                capacity[i][s] += temp;
                minFlow -= temp;
            }

    return save - minFlow;
}

void buildGraph(int maxE)
{
    int i, j;
    memset(capacity, 0, sizeof(capacity));
    for(i = K + 1; i <= K + C; i++)
        capacity[0][i] = 1;
    for(i = 1; i <= K; i++)
        capacity[i][K+C+1] = M;
    for(i = K + 1; i <= K + C; i++)
        for(j = 1; j <= K; j++)
        if(graph[i][j] <= maxE)
            capacity[i][j] = 1;
}

int maxFlow()
{
    int res = 0;
    while(BFS())
            res += DFS(0, INF);
    return res;
}

int binSearch()
{
    int l = 1, r = maxEdge(), mid;
    while(l < r){
        mid = (l + r)/2;
        buildGraph(mid);
        if(maxFlow() == C)
            r = mid;
        else
            l = mid + 1;
    }
    return r;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    int i, j;
    while(cin>>K>>C>>M){

        for(i = 1; i <= K + C; i++)
            for(j = 1; j <= K + C; j++){
                cin>>graph[i][j];
                if(!graph[i][j])
                    graph[i][j] = INF;
        }

        Floyd();
        cout<


你可能感兴趣的:(网络流)