No.100 - LeetCode741 - 取樱桃 - 最小费用最大流

本文深入探讨了网络流算法在网络优化问题中的应用,包括构建网络流模型、实现增广路径搜索和流量调整等关键步骤。通过具体实例展示了如何利用网络流算法解决实际问题,如资源分配和最短路径寻找。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网络流模版题:32ms

class Solution {
public:
    struct Edge{
        int from;
        int to;
        int flow;
        int var;
        int rvs;
        int pre;
        Edge(int a,int b,int c,int d,int e,int f):from(a),to(b),flow(c),var(d),rvs(e),pre(f){}
    };
    vector<Edge> E;
    int cnt;
    vector<int> pre;
    vector<int> path;
    vector<int> vis;
    vector<int> dis;
    int S,T;
    void addEdge(int from,int to,int flow,int var){
        E.push_back(Edge(from,to,flow,var,cnt+1,pre[from]));
        pre[from] = cnt++;
        E.push_back(Edge(to,from,0,-var,cnt-1,pre[to]));
        pre[to] = cnt++;
    }
    bool SPFA(){
        const int INF = 0x3f3f3f3f;
        for(int i=0;i<=T;i++) path[i] = vis[i] = 0,dis[i] = INF;
        queue<int> q;
        q.push(S);
        dis[S] = 0;
        while(!q.empty()){
            int now = q.front();
            q.pop();
            vis[now] = 0;
            for(int i=pre[now];i!=0;i=E[i].pre){
                if(E[i].flow > 0 && dis[now] + E[i].var < dis[E[i].to]){
                    dis[E[i].to] = dis[now] + E[i].var;
                    path[E[i].to] = i;
                    if(vis[E[i].to] == 0){
                        q.push(E[i].to);
                        vis[E[i].to] = 1;
                    }
                }
            }
        }
        if(dis[T] == INF) return false;
        return true;
    }
    int DFS(){
        const int INF = 0x3f3f3f3f;
        int Eid = path[T];
        int minflow = INF;
        while(Eid != 0){
            minflow = min(minflow,E[Eid].flow);
            Eid = path[E[Eid].from];
        }
        Eid = path[T];
        int ans = 0;
        while(Eid != 0){
            E[Eid].flow -= minflow;
            E[E[Eid].rvs].flow += minflow;
            ans += minflow*E[Eid].var;
            Eid = path[E[Eid].from];
        }
        return ans;
    }
    int cherryPickup(vector<vector<int>>& grid) {
        const int INF = 0x3f3f3f3f;
        int N = grid.size();
        int M = N*N;
        S = M+M; T = S+1;
        pre.reserve(T+1);
        path.reserve(T+1);
        vis.reserve(T+1);
        dis.reserve(T+1);
        for(int i=0;i<=T;i++) pre[i] = 0;
        cnt = 1;
        E.push_back(Edge(0,0,0,0,0,0));
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                if(grid[i][j] == -1) continue;
                addEdge(i*N+j,i*N+j+M,1,-grid[i][j]);
                addEdge(i*N+j,i*N+j+M,INF,0);
                if(i!=0) addEdge((i-1)*N+j+M,i*N+j,INF,0);
                if(j!=0) addEdge(i*N+j-1+M,i*N+j,INF,0);
            }
        }
        addEdge(S,0,2,0);
        addEdge(S-1,T,2,0);
        int ans = 0;
        while(SPFA()) ans+=DFS();
        return -ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值