POJ3422费用流

Posted df-yimeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ3422费用流相关的知识,希望对你有一定的参考价值。

Description:
  一个N * N的奖赏地图,你可以走k次这个地图,但是每一次你走过一个有分的节点,你获得得分,但这个节点的得分都要清零,问你走k次地图的最大得分

Solution:

  把得分变成负数就变成最小费用问题了,看看题目的要求进行建图,首先每个节点的访问次数最多也就k次,然后有分的点访问一次后就没分了,可以变成1,k-1的访问,所以转换成经典的拆点建图问题

  ·源点到入口 —— 容量k —— 费用0

  ·出口到汇点 —— 容量k —— 费用0

  ·地图中的节点拆分成x1,x2

    ·x1 - x2 加两次边 一次:容量为1 —— 费用是 - cost 另一次是 容量是k - 1 —— 费用是0

    ·x2 到其它可达点 —— 容量k —— 费用 0

所以写这篇博客目的也就是学习一下,生活条件的建图思想,把分数只能走一次转化成建两类边的思想,是精彩点

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define inf (1 << 28)
using namespace std;
const int maxn = 50500;
const int maxm = 100100;

int n,m,k;

struct node
{
    int to,val,cost,pre;
}e[maxm];
int id[maxn];
int cnt;
void add(int from,int to,int val,int cost)
{
    e[cnt].to = to;
    e[cnt].val = val;
    e[cnt].cost = cost;
    e[cnt].pre = id[from];
    id[from] = cnt++;
    swap(from,to);
    e[cnt].to = to;
    e[cnt].val = 0;
    e[cnt].cost = -cost;
    e[cnt].pre = id[from];
    id[from] = cnt++;
}
void init()
{
    memset(id,-1,sizeof(id));
    cnt = 0;
}

int dis[maxn];
int pre[maxn];
int path[maxn];
int vis[maxn];

bool spfa(int s,int t)
{
    memset(pre,-1,sizeof(pre));
    memset(vis,0,sizeof(vis));
    for(int i = 0;i < maxn ;++i)
        dis[i] = inf;
    dis[s] = 0;
    vis[s] = 1;
    queue<int> q;
    q.push(s);
    while(q.size())
    {
        int now = q.front();
        q.pop();

        for(int i = id[now];~i;i = e[i].pre)
        {
            int to = e[i].to;
            int val = e[i].val;
            int cost = e[i].cost;

            if(val > 0 && dis[now] + cost < dis[to])
            {
                dis[to] = dis[now] + cost;
                pre[to] = now;
                path[to] = i;
                if(!vis[to])
                {
                    vis[to] = 1;
                    q.push(to);
                }
            }
        }
        vis[now] = 0;
    }
    if(pre[t] == -1)return false;
    return true;
}
int mcmf(int s,int t)
{
    int c = 0;
    while(spfa(s,t))
    {
        int mf = inf;
        for(int now = t;now != s;now = pre[now])
        {
            if(e[path[now]].val < mf)
                mf = e[path[now]].val;
        }
        for(int now = t;now != s;now = pre[now])
        {
            e[path[now]].val -= mf;
            e[path[now]^1].val += mf;
            c += mf * e[path[now]].cost;
        }
    }
    return c;
}

int coss[55][55];
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        init();
        int s = 0;
        int t = 2 * n * n + 1;
        for(int i = 1;i <= n;++i)
        {
            for(int j = 1;j <= n;++j)
            {
                scanf("%d",&coss[i][j]);
            }
        }
        add(s,1,k,0);
        add(2*n*n,t,k,0);
        for(int i = 1;i <= n;++i)
        {

            for(int j = 1;j <= n;++j)
            {
                int id1 = (i - 1) * n + j;
                int id2 = n * n + id1;

                add(id1,id2,1,-coss[i][j]);
                add(id1,id2,k-1,0);
                if(i == n && j == n)continue;
                if(i + 1 > n)
                    add(id2,id1+1,k,0);
                else if(j + 1 > n)
                    add(id2,id1+n,k,0);
                else
                {
                    add(id2,id1+n,k,0);
                    add(id2,id1+1,k,0);
                }
            }
        }
        printf("%d
",mcmf(s,t) * -1 );
    }
    return 0;
}

 

  


以上是关于POJ3422费用流的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3422 矩阵取数 最小费用流拆点+负边

poj 3422 最大费用流

POJ 3422 最小费用最大流

POJ3422费用流

POJ3422 Kaka&#39;s Matrix Travels 最大费用最大流

[poj] 3422 Kaka's Matrix Travels || 最小费用最大流