POJ 2987 [Maximum Weight Closed Diagram]

The meaning of the question: n (0 < n ≤ 5000) individuals, m (0 ≤ m ≤ 60000) subordinate relationships, one person can gain or lose bi (|bi| ≤ 10 ^ 7, 1 ≤ i ≤ n) , firing a person will fire all his subordinates together, and ask how to fire people to maximize the profit, output the maximum profit and the minimum number of people fired.

Obvious conditions for maximum weight closure graphs. Find a minimum cut. For the minimum number of flippers, that is, which closed graph we choose will maximize the total revenue. The set of S in the minimum cut = s intersects V1, and this V1 is the desired one.
Therefore, after we have obtained the minimum cut, we use dfs to traverse from s, and the points that can be reached are all points in V1.

#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
#define MAX 5100
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

int ss, tt;
int kase;
int sum;
int n, m;
int cont;
int vis[MAX];
int head[MAX];
int divv[MAX];
int cur[MAX];
int cnt;
ll postive;
struct edge {
    int from, to, next;
    ll w;

}e[500000];

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) {
            ll w = e[i].w;
            int v = e[i].to;
            if (divv[v] == 0 && w) {
                divv[v] = divv[u] + 1;
                Q.push(v);
            }
        }

    }
    return 0;

}

ll DFS(int u, ll 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;
        ll 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 dfs(int s) {
    vis[s] = 1;
    for (int i = head[s]; i != -1; i = e[i].next) {
        int v = e[i].to;
        ll w = e[i].w;
        if (!vis[v] && w) {
            dfs(v);
            cnt++;
        }
    }

}
void Dinic() {
    ll ans = 0;

    while (makediv() == 1) {
        memcpy(cur, head, sizeof(head));
        ans += DFS(ss, INF, tt);
    }
    dfs(ss);
    printf("%d %I64d\n", cnt, postive - ans);
}

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

    }
    return 0;
}

Guess you like

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