• ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)


      将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0(保证可以多次通过该点,但费用只计算一次)。

      另外伪点B与原点右侧与下方的点有一条单向路(邻接表实现需要建立反向空边),残留容量为+∞,费用为0。源点0到点1有一条单向路,残留容量为K(可以通过K次),最后一个点的伪点2*n*n与汇点2*n*n+1有一条单向边,残留容量为K,两条边的费用都为0。

      构图成功后,走一次最小费用最大流即可。

    //最小费用最大流问题-拆点
    //Time:47Ms     Memory:624K
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define MAX 55
    #define MAXN 5005
    #define INF 0x3f3f3f3f
    struct Edge{
        int u,v,r,w,next;
        Edge(){}
        Edge(int U,int V,int R,int W,int N):u(U),v(V),r(R),w(W),next(N){}
    }e[MAXN*8];
    int n,k;
    int s,t;
    int h[MAXN],le;
    int m[MAX][MAX];
    int pre[MAXN];
    int cost[MAXN];
    bool vis[MAXN];
    void add(int u,int v,int r,int w)
    {
        e[le] = Edge(u,v,r,w,h[u]);   h[u] = le++;
        e[le] = Edge(v,u,0,-w,h[v]);   h[v] = le++;
    }
    void build()
    {
        add(s, 1, k, 0);
        add(2*n*n, t, k, 0);
        for(int i = 1; i <= n*n; i++)
        {
            add(i, n*n+i, 1, -m[(i - 1)/n + 1][(i - 1)%n + 1]);
            add(i, n*n+i, k, 0);
            if(i % n)   add(i+n*n, i+1, INF, 0);
            if(i <= n*(n-1))    add(i+n*n, i+n, INF, 0);
        }
    }
    bool spfa()
    {
        memset(pre,-1,sizeof(pre));
        memset(vis,false,sizeof(vis));
        memset(cost,INF,sizeof(cost));
        queue<int> q;
        q.push(s);
        cost[s] = 0;    vis[s] = true;
        while(!q.empty()){
            int cur = q.front();
            q.pop();    vis[cur] = false;
            for(int i = h[cur]; i != -1; i = e[i].next)
            {
                int v = e[i].v;
                if(e[i].r && cost[v] > cost[cur] + e[i].w){
                    cost[v] = cost[cur] + e[i].w;
                    pre[v] = i;
                    if(!vis[v]){
                        vis[v] = true;  q.push(v);
                    }
                }
            }
        }
        return cost[t] == INF? false: true;
    }
    int maxcostflow()
    {
        int maxFlow = 0;
        while(spfa()){  //增广路
            int mind = INF;
            for(int i = pre[t]; i != -1; i = pre[e[i].u])
                mind = min(mind, e[i].r);
            for(int i = pre[t]; i != -1; i = pre[e[i].u])
            {
                e[i].r -= mind;
                e[i^1].r += mind;
            }
            maxFlow += mind*cost[t];
        }
        return maxFlow;
    }
    int main()
    {
        //freopen("in.txt", "r", stdin);
        memset(h, -1, sizeof(h));
        scanf("%d%d", &n,&k);
        s = 0; t = 2*n*n+1;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%d", &m[i][j]);
        build();
        printf("%d
    ", -maxcostflow());
        return 0;
    }
    
  • 相关阅读:
    Redis Redis-Cell
    Redis Bloom Filter
    Redis HyperLogLog
    TCC、XA 、DTP区别
    MySQL索引最左匹配原则
    什么原因导致统计信息失效--SQL
    光标移动大法---落落大神
    mongo 导入导出
    oracle 10053 事件
    卸载12C
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5719179.html
Copyright © 2020-2023  润新知