Beer Problem


Time Limit: 2 Seconds      Memory Limit: 32768 KB

Everyone knows that World Finals of ACM ICPC 2004 were held in Prague. Besides its greatest architecture and culture, Prague is world famous for its beer. Though drinking too much is probably not good for contestants, many teams took advantage of tasting greatest beer for really low prices.

A new beer producing company Drink Anywhere is planning to distribute its product in several of the n European cities. The brewery is located near Prague, that we would certainly call city number 1. For delivering beer to other cities, the company is planning to use logistics company Drive Anywhere that provides m routes for carrying goods. Each route is described by the cities it connects (products can be transported in either direction), its capacity --- the number of barrels of beer that can be transported along this route each day, and the cost of transporting one barrel of beer along it. To deliver beer to some city it may be necessary (or advantageous) to use several routes consequently, and maybe even deliver beer using several different paths.

Each city is in turn characterized by the price that local pubs and restaurants are ready to pay for one barrel of beer. You may assume that demand for beer is essentially unlimited in each city, since this is the product that will always find its consumer.

Drink Anywhere is not planning to distribute its beer in Prague for a while, because of the high competition there, so it is just planning to provide beer to other cities for now. Help it to find out, what is the maximal income per day it can get.

Input

The first line of the input file contains n and m --- the number of cities in Europe we consider and the number of delivery routes respectively (2 ≤ n ≤ 100), 1 ≤ m ≤ 2000). The next line contains n - 1 integer numbers --- prices of a barrel of beer in European cities 2, 3 ..., n respectively (prices are positive integers and do not exceded 1000).

The following m lines contain four integer numbers each and describe delivery routes. Each route is specified by the numbers of cities it connects, its capacity, and the price of transporting one barrel of beer along it (the capacity and the price are positive integers, they do not exceed 1000).

There are multiple cases. Process to the end of file.

Output

Output the maximal income the company can get each day.

Sample Input

4 4
80 50 130
1 2 80 50
2 4 40 90
3 1 40 60
3 4 30 50

Sample Output

3000

Hint

The company should deliver 80 barrels of beer to the second city (using the first route it costs 50 per barrel to deliver beer, income is 30 per barrel, 2400 total), and 30 barrels to the fourth city (the best path uses routes 3 and 4, it costs 110 to deliver a barrel, income is 20 per barrel, 600 total). It is not profitable to deliver beer to the third city, so the company should not do it.

题目链接:ZOJ 3362

建图:构建源点S为0和汇点T为n+1,从S到1连一条流量为INF费用为0的边,然后由于可以卖无限多的酒给每一个城市,因此城市到汇点连一条流量为INF费用为正的该城市的售价的边,然后对于M条边添加双向边,流量均为所给的cap,费用均为负的单位运输费用。正负怎么看呢?由于我们求的是最大费用,但算法求的是最小费用流,因此把原来的边上的正的费用要取负值,但是售价又和运输费用相反,负负得正为正值。

然后这题一开始以为求的是最大费用最大流,但是当达到最大流的时候赚的钱却只有2900,且问题就出在多出来的10流量上,调试后发现当处理这10个流量的时候费用已经是负的了,因此当费用为负的时候就不要再进行增广即可。为什么一旦为负就可以不用再进行增广了呢?可以这样想,第一次增广的时候找到了可行流,然后从图中减掉了它,开始第二次增广,这时S到T的最短路肯定会由于残余流量的影响,至少这个最短距离是不会变短的,因此每一次增广费用距离总是不减的,当求最大费用的时候,显然就是不增的了,即保证了d[t]一旦为负后面均为负数且不会增大。

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 110;
const int M = 2010;
struct edge
{
int to, nxt, cap, cost;
edge() {}
edge(int _to, int _nxt, int _cap, int _cost): to(_to), nxt(_nxt), cap(_cap), cost(_cost) {}
};
edge E[(N + 2 * M) << 1];
int head[N], tot;
int d[N], pre[N], path[N];
bitset<N>vis;
int mc, mf; void init()
{
CLR(head, -1);
tot = 0;
mc = mf = 0;
}
inline void add(int s, int t, int cap, int cost)
{
E[tot] = edge(t, head[s], cap, cost);
head[s] = tot++;
E[tot] = edge(s, head[t], 0, -cost);
head[t] = tot++;
}
int spfa(int s, int t)
{
CLR(d, -INF);
int inf = d[0];
vis.reset();
CLR(pre, -1);
CLR(path, -1);
d[s] = 0;
vis[s] = 1;
queue<int>q;
q.push(s);
while (!q.empty())
{
int u = q.front();
q.pop();
vis[u] = 0;
for (int i = head[u]; ~i; i = E[i].nxt)
{
int v = E[i].to;
if (d[v] < d[u] + E[i].cost && E[i].cap > 0)
{
d[v] = d[u] + E[i].cost;
pre[v] = u;
path[v] = i;
if (!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
return d[t] != inf;
}
void MCMF(int s, int t)
{
int i;
while (spfa(s, t))
{
int Min = INF;
for (i = t; i != s && ~i; i = pre[i])
Min = min(Min, E[path[i]].cap);
for (i = t; i != s && ~i; i = pre[i])
{
E[path[i]].cap -= Min;
E[path[i] ^ 1].cap += Min;
}
if (d[t] < 0)
return ;
mf += Min;
mc += Min * d[t];
}
}
int main(void)
{
int n, m, a, b, c, d, i;
while (~scanf("%d%d", &n, &m))
{
init();
int S = 0, T = n + 1;
add(S, 1, INF, 0); //1
for (i = 2; i <= n; ++i)
{
scanf("%d", &d);
add(i, T, INF, d); //n
}
for (i = 0; i < m; ++i)
{
scanf("%d%d%d%d", &a, &b, &c, &d);
add(a, b, c, -d); //m
add(b, a, c, -d); //m
}
MCMF(S, T);
printf("%d\n", mc);
}
return 0;
}

ZOJ 3362 Beer Problem(SPFA费用流应用)的更多相关文章

  1. ZOJ 3362 Beer Problem

    Beer Problem Time Limit: 2000ms Memory Limit: 32768KB This problem will be judged on ZJU. Original I ...

  2. POJ 2175 spfa费用流消圈

    题意:给出n栋房子位置和每栋房子里面的人数,m个避难所位置和每个避难所可容纳人数.然后给出一个方案,判断该方案是否最优,如果不是求出一个更优的方案. 思路:很容易想到用最小费用流求出最优时间,在与原方 ...

  3. 最长可重区间集 spfa费用流

    给定实直线L上的n个开区间,和一个正整数k 选取若干个区间,在保证实直线L上的任意一个点最多被选出区间覆盖k次的情况下,使得这些区间的长度和最大 先把区间按照左端点排序, 考虑到重复其实就代表着相交, ...

  4. Spfa费用流模板

    ; ,maxm=; ,fir[maxn],nxt[maxm],to[maxm]; int cap[maxm],val[maxm],dis[maxn],path[maxn]; void add(int ...

  5. 洛谷.4015.运输问题(SPFA费用流)

    题目链接 嗯..水题 洛谷这网络流二十四题的难度评价真神奇.. #include <queue> #include <cstdio> #include <cctype&g ...

  6. BZOJ.4819.[SDOI2017]新生舞会(01分数规划 费用流SPFA)

    BZOJ 洛谷 裸01分数规划.二分之后就是裸最大费用最大流了. 写的朴素SPFA费用流,洛谷跑的非常快啊,为什么有人还T成那样.. 当然用二分也很慢,用什么什么迭代会很快. [Update] 19. ...

  7. ACdream 1128 Maze(费用流)

    题目链接:http://acdream.info/problem?pid=1128 Problem Description wuyiqi陷入了一个迷宫中,这个迷宫是由N*M个格子组成的矩阵.每个格子上 ...

  8. 【BZOJ】1061: [Noi2008]志愿者招募(费用流+数学)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1061 好神的一题! 学会了一种建模方式: 当方程组内的任意变量都在其中两个方程出现且一正一负,可以建 ...

  9. POJ2195 Going Home[费用流|二分图最大权匹配]

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22088   Accepted: 11155 Desc ...

随机推荐

  1. 六、react添加多个className报错解决方法

    例如<div className={style.calss1,style.class2}></div> 该方法会报错 想得到最终渲染的结果:<div class='cla ...

  2. java程序换图标

    ImageIcon img = new ImageIcon("D:\\mahou-in-action\\ShiJuanFenXi\\src\\zoom-in.png"); inst ...

  3. dn.net/blueheart20/article/details/22080489

    dn.net/blueheart20/article/details/22080489

  4. js点击拉拽轮播图pc端移动端适配

    <div class="content"> <button class="left">left</button> <b ...

  5. linux网络编程之断点传输文件

    以下载链接"http://www.boa.org/boa-0.94.13.tar.gz"为例: 断点续传实验大概步骤: ===================== 1,使用geth ...

  6. css清除浮动,清除子节点margin溢出问题

    清除浮动 .clearfix:after{ content:”.”; display:block; height:0; clear:both; visibility:hidden; } 清除margi ...

  7. url地址形式的传参格式拼接

    例子一: var gid=pid=pizi=sn=newsn=sn_price=city_id=123; var params = 'gid=' +123; params += '&pid=' ...

  8. PAT Basic 1084

    1084 外观数列 外观数列是指具有以下特点的整数序列: d, d1, d111, d113, d11231, d112213111, ... 它从不等于 1 的数字 d 开始,序列的第 n+1 项是 ...

  9. Linux命令之---pwd

    命令简介 Linux中用 pwd 命令用来查看”当前工作目录“的完整路径. 命令格式 pwd [选项] 命令功能和参数 功能:查看”当前工作目录“的完整路径:参数:一般情况下不带任何参数,如果目录是链 ...

  10. Redis实现之服务器

    命令请求的执行过程 一个命令请求从发送到获得回复的过程中,客户端和服务器需要完成一系列操作.举个栗子,如果我们使用客户端执行以下命令: 127.0.0.1:6379> SET KEY VALUE ...