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. ubuntu or centos 网卡无法启动

    [root@seasoned-bro:/home/daeh0f]# /etc/init.d/network restart Restarting network (via systemctl): Jo ...

  2. Java代码工具箱之链接Oracle

    1. 需要oracle的 odbc  jar包 2. 代码 3. 注意:ps对象和statement对象最好用完立即释放,尤其是读写数据库代码出现在 for 循环语句中时. 否则会出现游标不够的情况, ...

  3. 深入理解new String()

    一. 引言 new String("hello")这样的创建方式,到底创建了几个String对象? 二. 分析 String s1 = "HelloWorld" ...

  4. GreenPlum查看表和数据库大小

    表大小 zwcdb=# select pg_size_pretty(pg_relation_size('gp_test')); pg_size_pretty ---------------- 1761 ...

  5. 高性能可扩展MySQL数据库设计及架构优化 电商项目(慕课)第3章 MySQL执行计划(explain)分析

    ID:相同就从上而下,不同数字越大越优先

  6. 牛客NOIP普及组R1 C括号(dp)

    题意 题目链接 Sol maya普及组的dp都要想很长时间,我真是越来越菜了qwq 设$f[i][j]$表示当前到第$i$个位置,剩下$j$个左括号没被匹配 转移的时候判断一下即可 /* */ #in ...

  7. ATM-db-dnhandler

    import os,jsonfrom conf import settings def select(name): user_path = os.path.join(settings.BASE_DB, ...

  8. 37.VUE学习之-表单的综合运用

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...

  9. 01 python爬虫

    ---

  10. 权限组件(15):rbac的使用文档和在业务中的应用

    这里用主机管理系统当做示例. 一.将rbac组件拷贝到项目中. 注意: rbac自己的静态文件.layout.html(被继承的模板).bootstrap.fontsize.公共的css.jquery ...