poj 2112 Optimal Milking 【網絡流】

Problem:
有k個機器和c頭奶牛,一個機器最多可以供應m個奶牛使用,給定奶牛和機器之間的路徑(圖),問走的最遠的奶牛走的路最短有多遠?
Solution:
這道題難在不知道是網絡流的題目,首先需要轉換模型,設立一個超級起點向每一個奶牛的容量設置爲1,然後超級匯點,每一個機器向匯點容量爲m,題意就變成了在最大流是c的情況下距離如何最短?此時我們利用二分搜索,找到滿足最大流是c的情況下的最逼近的距離。利用dinic網絡流即可實現。
note:
1. 算法模板的效率一定要高,這樣才能保證上層封裝的效率,利用bfs模擬的dinic明顯不如現在的直接dfs效率高。
2. 要對模型有一定的敏感性。

#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<vector>
#include<fstream>
#include<list>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s,0,sizeof(s))

const double PI = 3.141592653589;
const int INF = 0x3fffffff;

int G[240][240];
int k, c, m;
int n;

void floyd(){
    for(int k = 1; k <= n; ++k)
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
}

const int maxn = 240;
int cap[maxn][maxn];
int layer[maxn];
bool visited[maxn];
int st, en;//start point, end point

bool count_layer() {
    queue<int> q;  q.push(st);
    memset(layer, -1, sizeof(layer));
    layer[st] = 0;

    while(!q.empty()) {
        int v = q.front();  q.pop();
        for(int i = st; i <= en; i++) {
            if(layer[i] == -1 && cap[v][i] > 0) {
                layer[i] = layer[v]+1;
                if(i == en)
                    return true;
                q.push(i);
            }
        }
    }
    return false;
}

int dfs(int root, int cur_flow) {
    int dt = cur_flow;//the rest of cur_flow
    if (root == en) return dt;
    for (int i = 0; i <= en; i++) {
        if (cap[root][i] > 0 && layer[i] == layer[root]+1) {
            int flow = dfs(i, min(dt, cap[root][i]));
            cap[root][i] -= flow;
            cap[i][root] += flow;
            dt -= flow;
        }
    }
    return cur_flow - dt;
}

int dinic() {
    int ans = 0;
    while(count_layer())
        ans += dfs(st, INF);
    return ans;
}

void reG(int w) {
    ms(cap);
    for(int i = k+1; i <= k+c; i++) {
        for(int j = 1; j <= k; j++) {
            cap[i][j] = (G[i][j] <= w) ? 1 : 0;
        }
    }
    for(int i = k+1; i <= k+c; i++)
        cap[0][i] = 1;
    for(int i = 1; i <= k; i++)
        cap[i][n+1] = m;
}

int main() {
//        freopen("/Users/really/Documents/code/input","r",stdin);
    //    freopen("/Users/really/Documents/code/output","w",stdout);
    ios::sync_with_stdio(false);

    cin >> k >> c >> m;
    n = k + c;
    en = n+1;
    st = 0;
    int w;
    for(int i = 1; i <= k+c; i++) {
        for(int j = 1; j <= k+c; j++) {
            cin >> w;
            G[i][j] = (w==0) ? INF : w;
        }
    }

    floyd();

    int l = 1, r = 40000;
    int mid;

    while(l < r) {
        mid = (l+r)/2;
        reG(mid);
        int t = dinic();
        if(t == c)
            r = mid;
        else
            l = mid+1;
    }
    cout << l << endl;

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章