码迷,mamicode.com
首页 > 其他好文 > 详细

poj-2112-Optimal Milking(最大流)

时间:2016-05-07 10:24:23      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:

传送门

题意:K个产奶机,C头奶牛,每个产奶机最多可供M头奶牛使用;并告诉了产奶机、奶牛之间的两两距离Dij(0<=i,j < K+c)。

问题:如何安排使得在任何一头奶牛都有自己产奶机的条件下,奶牛到产奶机的最远距离最短?最短是多少?

Dinic算法

先floyd求得两两之间最小距离,然后二分寻找答案


邻接链表的方法

#include <iostream> 
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 250
const int INF = 0x3f3f3f3f;
using namespace std;
struct node{
    int to, cap, next;
}edge[N*N];
int K, c, m, a[N][N], st, en, n, cnt;
int first[N], level[N], q[N];
int cap[N][N];
void read(int u, int v, int c){
    edge[cnt].cap = c;
    edge[cnt].next = first[u];
    edge[cnt].to = v;
    first[u] = cnt++;
    edge[cnt].cap = 0;
    edge[cnt].next = first[v];
    edge[cnt].to = u;
    first[v] = cnt++;
}
void init(int dis){
    cnt = 0;
    memset(first, -1, sizeof(first));
    n = K+c;
    st = 0;
    en = n+1;
    for (int i = 1; i <= K; i++){
        read(0, i, m);
    }
    for (int i = K+1; i <= n; i++){
        read(i, en, 1);
    }
    for (int i = 1; i <= K; i++){
        for (int j = K+1; j <= n; j++){
            if (a[i][j] <= dis){
                read(i, j, 1);
            }
        }
    }
}
bool bfs(int s, int t){
    memset(level, 0, sizeof(level));
    level[s] = 1;
    int rear = 0, front = 0;
    q[front++] = s;
    while(rear < front){
        int x = q[rear++];
        if (x == t) return true;
        for (int e = first[x]; e != -1; e = edge[e].next){
            int v = edge[e].to;
            int f = edge[e].cap;
            if (!level[v] && f){
                level[v] = level[x]+1;
                q[front++] = v;
            }
        }
    }
    return false;
}
int dfs(int u, int maxf, int t){
    if (u == t) return maxf;
    int ret = 0;
    for (int e = first[u]; e != -1; e = edge[e].next){
        int v = edge[e].to;
        int f = edge[e].cap;
        if (level[u]+1 == level[v] && f){
            int Min = min(maxf-ret, f);
            f = dfs(v, Min, t);
            edge[e].cap -= f;
            edge[e^1].cap += f;
            ret += f;
            if (ret == maxf)    return ret;
        }
    }
    return ret;
}
int dinic(int s, int t){
    int ans = 0;
    while(bfs(s, t))
        ans += dfs(s, INF, t);
    return ans;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
#endif
    int i, j, k;
    while(~scanf("%d%d%d", &K, &c, &m)){
        for (i = 1; i <= K+c; i++){
            for (j = 1; j <= K+c; j++){
                scanf("%d", &a[i][j]);
                if(a[i][j] == 0)    a[i][j] = INF;
            }
        }
        for (k = 1; k <= K+c; k++){
            for (i = 1; i <= K+c; i++){
                for (j = 1; j <= K+c; j++){
                    a[i][j] = min(a[i][j], a[i][k]+a[k][j]);
                }
            }
        }
        int ans = 1, low = 1, high = INF;
        while(low <= high){
            int mid = (low+high)>>1;
            init(mid);
            if (dinic(st, en) == c){
                ans = mid;
                high = mid-1;
            }else{
                low = mid+1;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

邻接矩阵做法,比邻接表略慢

#include <iostream> 
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 250
const int INF = 0x3f3f3f3f;
using namespace std;
int K, c, m, a[N][N], st, en, n;
int first[N], level[N], q[N];
int cap[N][N];
void Init(int dis){
    memset(cap, 0, sizeof(cap));
    n = K+c;
    st = 0;
    en = n+1;
    for (int i = 1; i <= K; i++){
        cap[0][i] = m;
    }
    for (int i = K+1; i <= n; i++){
        cap[i][en] = 1;
    }
    for (int i = 1; i <= K; i++){
        for (int j = K+1; j <= n; j++){
            if (a[i][j] <= dis)
                cap[i][j] = 1;
        }
    }
}
bool bfs(int s, int t){
    memset(level, 0, sizeof(level));
    level[st] = 1;
    int rear = 0, front = 0;
    q[front++] = st;
    while(rear < front){
        int v = q[rear++];
        if (v == en)    return true;
        for (int i = 0; i <= K+c+1; i++){
            if (!level[i] && cap[v][i]){
                level[i] = level[v] + 1;
                q[front++] = i;
            }
        }
    }
    return false;
}
int dfs(int u, int maxf, int t){
    if (u == t) return maxf;
    int ret = 0, f;
    for (int i = 1; i <= K+c+1; i++){
        if (level[u] + 1 == level[i] && cap[u][i]){
            f = dfs(i, min(cap[u][i], maxf-ret), t);
            cap[u][i] -= f;
            cap[i][u] += f;
            ret += f;
            if (ret == maxf)    return ret;
        }
    }
    return ret;
}
int dinic(int s, int t){
    int ans = 0;
    while(bfs(s, t))
        ans += dfs(s, INF, t);
    return ans;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
#endif
    int i, j, k;
    while(~scanf("%d%d%d", &K, &c, &m)){
        for (i = 1; i <= K+c; i++){
            for (j = 1; j <= K+c; j++){
                scanf("%d", &a[i][j]);
                if(a[i][j] == 0)    a[i][j] = INF;
            }
        }
        for (k = 1; k <= K+c; k++){
            for (i = 1; i <= K+c; i++){
                for (j = 1; j <= K+c; j++){
                    a[i][j] = min(a[i][j], a[i][k]+a[k][j]);
                }
            }
        }
        int ans = 1, low = 1, high = INF;
        while(low <= high){
            int mid = (low+high)>>1;
            Init(mid);
            if (dinic(st, en) == c){
                ans = mid;
                high = mid-1;
            }else{
                low = mid+1;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

poj-2112-Optimal Milking(最大流)

标签:

原文地址:http://blog.csdn.net/qq_21120027/article/details/51332651

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!