POJ 3469 [Minimum Discount]

Description
n tasks, two machines AB, input n pairs of numbers Ai, Bi represents the consumption of task i on A and on B. , and then give m lines, each line with three numbers a, b, c, indicating that if a task and b task do not work on the same machine, an additional cost of c is required.
Ask
the minimum cost when all tasks work The consumption of the last M lines is three integers a, b, c per line, indicating that if the a task and the b task do not work on the same machine, the additional cost of c
Output is required to
output the minimum cost when all tasks are working.

When I first saw this question, I still can't build a map. . . . Then I saw that the solution to the problem was also very confusing. I didn't understand why it was enough to connect the corresponding limited points with a bidirectional edge with a capacity of c. . . .
The first is the minimum cut:
why the minimum cut? Because from the ST path, both options A and B are selected, but we only have to choose one of the options. Therefore, cutting edges are required.
For limited cases:

![](https://images2018.cnblogs.com/blog/1195472/201805/1195472-20180502091621193-434704619.jpg)

When the two-way edges are connected in this way, an S-2-3-T augmentation path will be found. An augmentation path of S-3-2-T will also be found, and this result is correct.
If there is only one-way edge between 2-3, then S-2-3-T is the optimal result after the road is found, but in fact, the data of 1000 should be added, because 2 and 3 use different the core. So it is wrong to connect only one-way edges.
Personal feeling is because the value of 1000 will not be added to the result in this kind of graph, so the existence of the edge of 1000 is a limitation.
Come up with a better explanation later.

#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
#define MAX 4000000
#define INF 0x1f1f1f1f
using namespace std;
int ss, tt;
int n, m;
int cont;
int head[MAX];
int divv[MAX];
int cur[MAX];
struct edge {
    int from, to, w, next;

}e[MAX];

void add(int u, int v, int w) {
    e[cont].from = u;
    e[cont].to = v;
    e[cont].w = w;
    e[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 = e[i].next) {
            int w = e[i].w;
            int v = e[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 = e[i].next) {
        int v = e[i].to;
        int w = e[i].w;
        if (divv[v] == divv[u] + 1 && w) {
            int f = DFS(v, min(maxflow - ret, w), tt);
            e[i].w -= f;
            e[i ^ 1].w += f;
            ret += f;
            if (ret == maxflow)
                return ret;

        }
    }
    return ret;
}

void Dinic() {
    int ans = 0;

    while (makediv() == 1) {
        memcpy(cur, head, sizeof(head));
        ans += DFS(ss, INF, tt);
    }

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


int main(void) {
    while (~scanf("%d%d", &n, &m)) {
        memset(head, -1, sizeof(head));
        cont = 0;
        ss = 0;
        tt = n + 1;
        for (int i = 1; i <= n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            add(ss, i, u);
            add(i, ss, 0);
            add(i, tt, v);
            add(tt, i, 0);
        }
        int u, v, w;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
            add(v, u, w);
        }
        Dinic();

    }


    return 0;


}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325161589&siteId=291194637