[Network flow 24 questions] B. Space flight planning problem (the maximum weight closed graph to the minimum cut, the minimum cut plan output)

A collated collection of algorithm templates: ACM templates


B. Space flight planning problem (from closed graph with maximum weight to minimum cut, output from minimum cut plan) [Province/NOI-]

P2762 Space flight plan problem

Insert picture description here

【problem analysis】

The maximum weight closed graph problem can be transformed into a minimum cut problem, and then solved with maximum flow.

【Modeling method】

Consider each experiment as a vertex in the set of bipartite graph X, and each device as a vertex in the set of bipartite graph Y, and add source S and sink T.
1. Connect a directed edge with a capacity of income from S to each Xi.
2. Connect a directed edge whose capacity is expenditure at that point from Yi to T.
3. If an experiment i requires equipment j, connect a directed edge with infinite capacity from Xi to Yj.

Count that the income of all experiments is only the same as Total, and find the maximum flow of the network Maxflow, the maximum profit is Total-Maxflow. The corresponding solution is the point in the S set divided by the minimum cut, that is, the vertex that can be accessed from S when the blocking flow is found in the last augmentation.

【Modeling analysis】

Define a S set divided by a cut as a solution, then the sum of the capacity of the cut set is (the weight of the vertices in the unselected A set + the weight of the vertices in the selected B set), denoted as Cut . The sum of the weights of all vertices in the A set is recorded as Total, then Total-Cut is (the weight of the vertices in the selected A set-the weight of the vertices in the selected B set), which is our goal Function, denoted as A. To maximize the objective function A, it is necessary to make Cut as small as possible, Total is a fixed value, so when the objective function A reaches the maximum value, Cut is the smallest, which is the smallest cut.

The general model of this problem is the closed graph with maximum weight. For related discussion, see Hu Botao, author of "The Application of the Minimum Cut Model in Informatics Competition".

[Reflection and Summary]

The experimental equipment that is cut off is the experimental equipment used, and the experiment that is cut off is the experiment that is not done, so all we cut off are expenses. We get the maximum benefit by subtracting the minimum cost from the total estimated revenue.
For all the paths from the source point to the sink point, we either cut off the experiment, which means not to do this experiment, or cut off the experimental instrument, which means to buy this instrument, then all the experiments (the experiments connected to it) that need this instrument It can be done.
Since the edge between experiment and equipment is inseparable, a (experimental equipment to be used) must be concentrated at the point of A (experiment to be done); and b (experimental equipment not to be used) and A (to be done) There is no connection between experiments, so it can't be connected to the source through A (the experiment to be done), it can only belong to the same set with B (all the experiments not done)!
We assign values ​​to the edges in this way, and for each cut, use the bonus of all experiments ( w A + w B w_A+w_BwA+wB​) minus the cut ( w B + wa w_B+w_awB+wa) Is the answer to this scheme ( w A − wa w_A-w_awAwa ), the maximum answer is to minimize the cut value.

The final output scheme:
The advantage of using Dninc to find the maximum flow is that it is convenient for us to output, because if the number of layers is INF, then obviously the capacity of the edge is greater than 0, which means that there is no traffic flowing through this edge, so it is obviously connected to it The experiment or equipment is not used (because the capacity of the side will become 0 if used), just output it directly.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>

using namespace std;
typedef long long ll;
const int N = 500007, M = 5000007, INF = 0x3f3f3f3f;

inline int read(int &x)
{
    
    
    char c;x = 0;
    while(c < '0' || c > '9')c = getchar();
    while(c >= '0' && c <= '9'){
    
    x = x * 10 + c - '0';c = getchar();}
    return c == '\r' || c == '\n' ? 0 : 1;
}

int n, m;
int head[N], ver[M], nex[M], tot;
int deep[N];
int cur[N], S, T;
ll maxflow, edge[M];

void add(int x, int y, int z, bool o = 1){
    
    
    ver[tot] = y;
    edge[tot] = z;
    nex[tot] = head[x];
    head[x] = tot ++ ;
    if(o)add(y, x, 0, 0);
}

bool bfs()
{
    
    
    memset(deep, 0x3f, sizeof deep);
    queue<int>q;
    q.push(S), deep[S] = 0, cur[S] = head[S];
    while(q.size())
    {
    
    
        int x = q.front();
        q.pop();
        for(int i = head[x]; ~i; i = nex[i]){
    
    
            int y = ver[i], z = edge[i];
            if(z > 0 && deep[y] == INF){
    
    
                q.push(y);
                deep[y] = deep[x] + 1;
                if(y == T)return true;
            }
        }
    }
    return false;
}

ll dfs(int x, ll flow)
{
    
    
    if(x == T)return flow;
    ll ans = 0, i, k;
    for(i = cur[x]; ~i && flow; i = nex[i]){
    
    
        cur[x] = i;
        int y = ver[i];
        ll z = edge[i];
        if(edge[i] > 0 && (deep[y] == deep[x] + 1))
        {
    
    
            k = dfs(y, min(flow, z));
            if(!k)deep[y] = 0;//待定
            edge[i] -= k;
            edge[i ^ 1] += k;
            ans += k;
            flow -= k;
        }
    }
    if(!ans)deep[x] = INF;//流量不为零,说明不是最小割
    return ans;
}

void dinic()
{
    
    
    while(bfs()){
    
    
        for(int i = 1; i <= n + m + 1; ++ i)
            cur[i] = head[i];
        maxflow += dfs(S, INF);
    }

}

int main()
{
    
    
    memset(head, -1, sizeof head);
    scanf("%d%d", &n, &m);
    S = 0, T = n + m + 1;
    ll sum = 0;

    for(int i = 1; i <= n; ++ i){
    
    
        int x, ch;
        ch = read(x);
        sum += x;
        add(S, i, x);
        while(ch){
    
    
            ch = read(x);
            add(i, x + n, INF);
        }
    }
    for(int i = 1; i <= m; ++ i){
    
    
        int x;
        scanf("%d", &x);
        add(i + n, T, x);
    }
    dinic();

    ll ans = sum - maxflow;


    for(int i = 1; i <= n; ++ i)
        if(deep[i] != INF)printf("%d ", i);
    puts("");
    for(int i = 1; i <= m; ++ i)
        if(deep[n + i] != INF)printf("%d ", i);
    puts("");
    printf("%lld\n", ans);
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_45697774/article/details/108653378