UVA-3231 Fair Share 二分流量

题面

链接:https://vjudge.net/problem/UVALive-3231

题意

给定n个机器,m个工作,每个工作可以给两个机器中的某一个做,问每台机器做的工作的最大值最小是多少

题解

网络流

首先源点向每个工作连一条容量为1的边,代表每个工作只能被做一次,然后每个工作向机器连边,容量为1,每个机器向汇点怎么连边呢?为了让每个机器做的工作量最大值最小,我们可以二分答案,机器向汇点连边,容量为二分的值,如果满流,说明每个工作都有人做,可以继续减小,最小值就是答案

代码

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 20050;
struct node {
    int v, cap, nxt;
    node () {}
    node (int v, int cap, int nxt): v(v), cap(cap), nxt(nxt) {}
} edge[N * 100];
int head[N], tot;
void init() {
    memset(head, -1, sizeof(head));
    tot = 0;
}
int dep[N];
void adde(int u, int v, int w) {
    edge[tot] = node(v, w, head[u]);
    head[u] = tot++;
    edge[tot] = node(u, 0, head[v]);
    head[v] = tot++;
}
int cur[N];
int gap[N];
int pre[N];
int sap(int s, int t, int n) {
    memset(dep, 0, sizeof(dep));
    memset(gap, 0, sizeof(gap));
    memcpy(cur, head, sizeof(head));
    memset(pre, 0, sizeof(pre));
    gap[0] = n;
    int u = s;
    pre[u] = -1;
    int ans = 0;
    while (dep[s] < n) {
        if (u == t) {
            int minn = inf;
            for (int i = pre[u]; ~i; i = pre[edge[i ^ 1].v]) {
                if (minn > edge[i].cap) minn = edge[i].cap;
            }
            for (int i = pre[u]; ~i; i = pre[edge[i ^ 1].v]) {
                edge[i].cap -= minn;
                edge[i ^ 1].cap += minn;
            }
            u = s;
            ans += minn;
            continue;
        }
        bool flag = false;
        int v;
        for (int i = cur[u]; ~i; i = edge[i].nxt) {
            v = edge[i].v;
            if (edge[i].cap && dep[v] + 1 == dep[u]) {
                flag = true;
                cur[u] = pre[v] = i;
                break;
            }
        }
        if (flag) {
            u = v;
            continue;
        }
        int minn = n;
        for (int i = head[u]; ~i; i = edge[i].nxt) {
            if (edge[i].cap && dep[edge[i].v] < minn) {
                minn = dep[edge[i].v];
                cur[u] = i;
            }
        }
        gap[dep[u]]--;
        if (!gap[dep[u]]) return ans;
        dep[u] = minn + 1;
        gap[dep[u]]++;
        if (u != s) u = edge[pre[u] ^ 1].v;
    }
    return ans;
}
int a[N], b[N];
int main () {
    int cse;
    scanf("%d", &cse);
    while (cse--) {
        init();
        int n, m;
        scanf("%d%d", &n, &m);
        int s = 0, t = n + m + 1;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d", &a[i], &b[i]);
        }
        int l = 0, r = 20000;
        int ans = inf;
        while (l <= r) {
            int mid = (l + r) >> 1;
            init();
            for (int i = 1; i <= m; i++) {
                adde(i, a[i] + m, 1);
                adde(i, b[i] + m, 1);
                adde(s, i, 1);
            }
            for (int i = 1; i <= n; i++) {
                adde(i + m, t, mid);
            }

            int now = sap(s, t, n + m + 2);
            if (now == m) {
                ans = min(ans, mid);
                r = mid - 1;
            }
            else l = mid + 1;
        }
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/artoriax/p/12203477.html