LightOJ 1071 - Baker Vai 最大费用流

原创 2016年05月31日 09:29:16

题目:http://www.lightoj.com/volume_showproblem.php?problem=1071


题意:给定一个n * m的矩阵,每个单元都有一个值,现在从左上走到右下再回到左上,中间不走重复的点,求所走单元的和的最大值


思路:这道题也算是费用流的经典题目了,不过用dp也能做。对于每个点,因为只能走一次,所以拆点连边做限制,容量为1,而起点终点要走两次,所以容量为2。把单元中的数字作为边的费用,这题是求最大和,所以可以先对费用取反,spfa能处理负权,求出来的最短路再取反就可以了。不过直接用spfa求最长路也行啊。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

const int N = 10010;
const int INF = 0x3f3f3f3f;
struct edge
{
    int st, to, cap, cost, next;
}g[N*10];
int mpa[110][110], head[N*2], dis[N*2], pre[N*2];
int n, m, cnt, _case = 0;
bool used[N*2];
void add_edge(int v, int u, int cap, int cost)
{
    g[cnt].st = v, g[cnt].to = u, g[cnt].cap = cap, g[cnt].cost = cost, g[cnt].next = head[v], head[v] = cnt++;
    g[cnt].st = u, g[cnt].to = v, g[cnt].cap = 0, g[cnt].cost = -cost, g[cnt].next = head[u], head[u] = cnt++;
}
int mcmf(int s, int t, int f)
{
    int res = 0;
    while(f > 0)
    {
        memset(dis, 0x3f, sizeof dis);
        memset(used, 0, sizeof used);
        memset(pre, -1, sizeof pre);
        queue<int> que;
        dis[s] = 0;
        used[s] = true;
        que.push(s);
        while(! que.empty())
        {
            int v = que.front(); que.pop();
            for(int i = head[v]; i != -1; i = g[i].next)
            {
                int u = g[i].to;
                if(g[i].cap > 0 && dis[u] > dis[v] + g[i].cost)
                {
                    dis[u] = dis[v] + g[i].cost;
                    pre[u] = i;
                    if(!used[u])
                        used[u] = true, que.push(u);
                }
            }
            used[v] = false;
        }
        if(dis[t] == INF) return -1;
        int d = f;
        for(int i = pre[t]; i != -1; i = pre[g[i].st])
            d = min(d, g[i].cap);
        f -= d;
        res += dis[t] * d;
        for(int i = pre[t]; i != -1; i = pre[g[i].st])
            g[i].cap -= d, g[i^1].cap += d;
    }
    return res;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        cnt = 0;
        memset(head, -1, sizeof head);
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                scanf("%d", &mpa[i][j]);

        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
            {   //对每个点拆点连边,其中起点终点要走两次,所以容量为2,其余点只能走一次,容量为1
                if((i == 0 && j == 0) || (i == n - 1 && j == m - 1))
                    add_edge(i * m + j, i * m + j + n * m, 2, 0);
                else add_edge(i * m + j, i * m + j + n * m, 1, 0);
                if(i != n - 1)
                    add_edge(i * m + j + n * m, (i+1) * m + j, 1, -mpa[i+1][j]);
                if(j != m - 1)
                    add_edge(i * m + j + n * m, i * m + (j + 1), 1, -mpa[i][j+1]);
            }
        int res = -mcmf(0, 2 * n * m - 1, 2);
        printf("Case %d: %d\n", ++_case, res + mpa[0][0] - mpa[n-1][m-1]);
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

LightOJ - 1071-Baker Vai (最小费用流)

原题地址:点击打开链接 题意:给你一个矩阵,每个点上都有一个数字代表需要被救的人数,你从(1,1)点出发开始救人走过的点不能再走,不过你只能向右或者向下走,到达终点后(m,n)返回起点,只能向上或者...

lightoj 1071 Baker Vai (思维dp)

lightoj 1071 Baker Vai (思维dp)

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

LightOJ 1071 - Baker Vai(水DP)

题意:两个机器人从(1, 1)到(n, m),除了终点外不可相遇。求路径最大价值。 思路:水DP。 #include #include #include #include #include...

POJ-2195 Going Home (最小费用最大流初学 && 最大权二分匹配—KM算法)

Going Home 最小费用最大流 && 最大权二分匹配,两种解法 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:...

poj3680将最大权重转换为最小费用流

//思路:将N个区间的端点当成顶点,然后区间连边,容量为1那么每个区间选择一次, //同时根据可以被K个区间覆盖让流量为K那么从i点到j点的流量和为K保证每个区间不被包含K次以上 //转换成最短路...

HIT 2715 Matrix3(最大费用最大流)

Matrix3 My Tags   (Edit)   Source : bin3   Time limi...

2726 Plan(最大费用流)

类似二取方格数 , fj有2个房子出租,1000个order , 给出order的时间范围和pay,求如何安排能得到最大的收益 TLE的构图方式:以order为点,设一组源汇和一组超级源汇,对每个o...

POJ--Kaka's Matrix Travels【最大费用最大流 && 经典建图 && 好题】

Kaka's Matrix Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8741   Acce...

HDU 3395 Special Fish(最大费用流)

Special Fish Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T...

【有上下界最大费用可行流】HDU-4862 Jump

Jump Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)