POJ 2112【最短路+二分+网络流】

题目描述:(转)k个机器,每个机器最多服务m头牛。c头牛,每个牛需要1台机器来服务。告诉你牛与机器每个之间的直接距离。问:让所有的牛都被服务的情况下,使走的最远的牛的距离最短,求这个距离。

#include<stdio.h>
#include<string.h>
#include<queue>
#define maxn 1000
#define INF 0x3f3f3f3f

using namespace std;
int k, m, c;
struct e {
    int from, to, w, next;
}edge[1000000];
int ss, tt;
int cur[maxn];
int cont;
int head[maxn];
int map[maxn][maxn];
int dis[maxn][maxn];
int divv[maxn];

void add(int u, int v, int w) {
    edge[cont].from = u;
    edge[cont].to = v;
    edge[cont].w = w;
    edge[cont].next = head[u];
    head[u] = cont++;
}

int makediv() {
    memset(divv, 0, sizeof(divv));
    divv[ss] = 1;
    queue<int> Q;
    Q.push(ss);
    while (!Q.empty()) {
        int u = Q.front();
        if (u == tt)
            return 1;
        Q.pop();
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int w = edge[i].w;
            int v = edge[i].to;
            if (divv[v] == 0 && w) {
                divv[v] = divv[u] + 1;
                Q.push(v);
            }
        }

    }
    return 0;

}

int DFS(int u, int maxflow, int tt) {
    if (u == tt)
        return maxflow;
    int ret = 0;
    for (int &i = cur[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        int w = edge[i].w;
        if (divv[v] == divv[u] + 1 && w) {
            int f = DFS(v, min(maxflow - ret, w), tt);
            edge[i].w -= f;
            edge[i ^ 1].w += f;
            ret += f;
            if (ret == maxflow)
                return ret;

        }
    }
    return ret;
}

bool Dinic(int mid) {
    int ans = 0;
    for (int i = 1; i <= k; i++) {
        add(ss, i, m);
        add(i, ss, 0);
    }
    for (int i = k + 1; i <= k + c; i++) {
        add(i, tt, 1);
        add(tt, i, 1);
    }

    for (int i = k + 1; i <= k + c; i++) {
        for (int j = 1; j <= k; j++) {
            if (map[i][j] <= mid) {
                add(j, i, 1);
                add(i, j, 0);
            }
        }

    }

    while (makediv() == 1) {
        memcpy(cur, head, sizeof(head));
        ans += DFS(ss, INF, tt);
    }
    if (ans == c)
        return true;
    else
        return false;
}

void Solve() {
    int l = 1, r = 10000;
    int mid;
    while (l <= r) {
        cont = 0;
        memset(head, -1, sizeof(head));
        mid = (l + r) / 2;
        if (Dinic(mid)) {
            r = mid - 1;
        }
        else {
            l = mid + 1;

        }
    }
    printf("%d\n", l);

}

void floyd() {
    for (int t = 1; t <= k + c; t++)
        for (int i = 1; i <= k + c; i++) {
            for (int j = 1; j <= k + c; j++) {
                if (map[i][t] + map[t][j] < map[i][j])
                    map[i][j] = map[i][t] + map[t][j];
            }
        }
}

int main(void) {
    while (~scanf("%d%d%d", &k, &c, &m)) {
        ss = 0;
        tt = k + c + 1;

        for (int i = 1; i <= k + c; i++) {
            for (int j = 1; j <= k + c; j++) {
                int w;
                scanf("%d", &w);
                if (i != j && !w)
                    map[i][j] = INF;
                else
                    map[i][j] = w;
            }

        }
        floyd();
        Solve();



    }

    return 0;


}

猜你喜欢

转载自www.cnblogs.com/tennant/p/8973801.html