费用流模板

template<int N,typename T>
struct CostFlow {
    int s,t,head[N],etot,prevv[N],preve[N],inq[N],que[N],qf,qe;
    T dis[N];
    struct Edge {int v,next; T cap,cost;} g[501000];
    void init() {
        memset(head,-1,sizeof(head)); etot = 0;
    }
    void add_edge(int u,int v,T cap,T cost) {
        //puts("dd");
        g[etot].v = v; g[etot].cap = cap; g[etot].cost = cost; g[etot].next = head[u]; head[u] = etot ++;
        g[etot].v = u; g[etot].cap = 0; g[etot].cost = -cost; g[etot].next = head[v]; head[v] = etot ++;
    }
    void mcmf(int _s,int _t,T &cost,T &flow) {
        //puts("FF");
        s = _s; t = _t; cost = flow = 0;
        while (true) {
            for (int i = 0; i < N; i ++) dis[i] = (T)1e30;
            dis[s] = 0;
            qf = qe = 0;
            que[qe++] = s;
            while (qf!=qe) {
                int u = que[qf++]; inq[u] = 0; if (qf==N) qf = 0;
                for (int i = head[u]; i != -1; i = g[i].next) {
                    Edge &e = g[i];
                    if (e.cap && dis[e.v]>dis[u]+e.cost) {
                        dis[e.v] = dis[u]+e.cost;
                        prevv[e.v] = u; preve[e.v] = i;
                        if (!inq[e.v]) {
                            que[qe++] = e.v;
                            if (qe==N) qe = 0;
                            inq[e.v] = 1;
                        }
                    }
                }
            }
            if (dis[t]==T(1e30)) break;
            T f = (T)1e30;
            for (int u = t; u != s; u = prevv[u])
                f = min(f,g[preve[u]].cap);
            cost += f*dis[t];
            flow += f;
            for (int u = t; u != s; u = prevv[u])
                g[preve[u]].cap -= f,g[preve[u]^1].cap += f;
        }
    }
   // cout<<flow<<cost<<endl;
   // printf("FF %d %d\n",(int)flow,(int)cost);
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值