zoukankan      html  css  js  c++  java
  • POJ_2112 Optimal Milking(网络流)

      /*昨晚写把Dinic写错了,一直不出结果,也没调出来,睡觉之前猛然想起来,少了
    一个break,造成死循环了。今天把那地方改过来,交上去WA。然后又重新敲之,TLE。
    后来检查了一遍,发现是Floyd写错了,改过后终于过了,发现网络流太容易错了。

      思路:

    1、用Floyd把每个奶牛到每个挤奶机的距离算出来,然后问题就变成了已知c头奶牛到
    k个挤奶机的距离,求走最远距离的牛走的路程mindis最小是多少。

    2、然后建网络流模型,每头奶牛和挤奶机都是一个结点。设一个源点s,s到c头奶牛
    的容量都记为1,k个挤奶机到汇点T的距离都记为m。

    3、先假设一个mindis的值,然后当奶牛到挤奶机的距离小于mindis时,奶牛结点到挤
    奶机结点的容量为1。

    4、用一次Dinic()求出最大流,如果 Dinic() == c,mindis减小重复3步骤,直到找
    到最小距离。


    My Code:
    */

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>

    using namespace std;

    const int N = 300;
    const int inf = 0x6fffffff;

    int map[N][N];
    int g[N][N];
    int layer[N];
    bool vis[N];
    int T, n;

    bool Layer() {
    int i, v;
    deque<int> q;
    memset(layer, -1, sizeof(layer));
    q.push_back(0);
    layer[0] = 0;
    while(!q.empty()){
    v = q.front();
    q.pop_front();
    for(i = 0; i <= T; i++) {
    if(g[v][i] > 0 && layer[i] == -1) {
    layer[i] = layer[v] + 1;
    if(i == T) {q.clear(); return true;}
    else q.push_back(i);
    }
    }
    }
    return false;
    }

    int Dinic() {

    deque<int> q;
    int v, i, vs, ve, min, min_s, sum = 0;
    while(Layer()) {
    memset(vis, false, sizeof(vis));
    vis[0] = true;
    q.push_back(0);
    while(!q.empty()) {
    v = q.back();
    if(v == T) {
    min = inf;
    for(i = 1; i < q.size(); i++) {
    vs = q[i-1]; ve = q[i];
    if(g[vs][ve] > 0 && min > g[vs][ve]) {
    min = g[vs][ve];
    min_s = vs;
    }
    }
    sum += min;
    for(i = 1; i < q.size(); i++) {
    vs = q[i-1]; ve = q[i];
    if(g[vs][ve] > 0) {
    g[vs][ve] -= min;
    g[ve][vs] += min;
    }
    }
    while(!q.empty() && q.back() != min_s) {
    vis[q.back()] = false;
    q.pop_back();
    }
    } else {
    for(i = 0; i <= T; i++) {
    if(g[v][i] > 0 && !vis[i] && layer[i] == layer[v] + 1) {
    vis[i] = true;
    q.push_back(i);
    break;
    }
    }
    if(i > T) q.pop_back();
    }
    }
    }
    return sum;
    }

    void built(int dis, int k, int m) {
    int i, j;
    memset(g, 0, sizeof(g));
    for(i = k+1; i <= n; i++) {
    g[0][i] = 1;
    for(j = 1; j <= k; j++) {
    if(map[i][j] <= dis) g[i][j] = 1;
    }
    }
    for(i = 1; i <= k; i++) {
    g[i][T] = m;
    }
    }

    void Floyd() {
    int i, j, k;
    for(k = 1; k <= n; k++) {
    for(i = 1; i <= n; i++) {
    for(j = 1; j <= n; j++) {
    if(i != j && map[i][k] != inf && map[k][j] != inf && map[i][k] + map[k][j] < map[i][j]){
    map[i][j] = map[i][k] + map[k][j];
    }
    }
    }
    }
    }

    int main() {
    //freopen("data.in", "r", stdin);

    int k, c, m, i, j, ans;
    int l, r, mid;

    scanf("%d%d%d", &k, &c, &m);{
    n = k + c; T = n + 1;
    memset(map, 0, sizeof(map));

    for(i = 1; i <= n; i++) {
    for(j = 1; j <= n; j++) {
    scanf("%d", &map[i][j]);
    if(map[i][j] == 0) map[i][j] = inf;
    }
    }
    Floyd();
    l = 0, r = inf - 10;
    while(l < r) {
    mid = (l + r) >> 1;

    built(mid, k, m);
    ans = Dinic();
    //printf("%d %d\n", ans, mid);
    if(ans == c) r = mid;
    else l = mid + 1;
    }
    printf("%d\n", r);
    }
    return 0;
    }
  • 相关阅读:
    POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)
    LCA 最近公共祖先 (模板)
    线段树,最大值查询位置
    带权并查集
    转负二进制
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    UVALive 3295 Counting Triangles
    POJ 2752 Seek the Name, Seek the Fame (KMP)
    UVA 11584 Partitioning by Palindromes (字符串区间dp)
  • 原文地址:https://www.cnblogs.com/vongang/p/2249485.html
Copyright © 2011-2022 走看看