https://www.lydsy.com/JudgeOnline/problem.php?id=106152

对于一个点对上多个点,不太容易建图的时候,考虑逆向思考

申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难
题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要
Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用
是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这
并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。
Input
  第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负
整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了
方便起见,我们可以认为每类志愿者的数量都是无限多的。
Output
  仅包含一个整数,表示你所设计的最优方案的总费用。 Sample Input Sample Output Hint
≤ N ≤ , ≤ M ≤ ,题目中其他所涉及的数据均 不超过2^-。

题意

虽然我读完题知道这是一个费用流,但是始终想不到应该怎么建图,在我觉得这题不可能建图的时候看了一下题解。

才知道世界之大无奇不有。

原本正常的建图是以源点连到左边,志愿者连到他对应的天数,但是首先边会很多,并且费用也很难表示,建图的过程显得困难重重。

但是如果换一种方法。

我们将这个点需要多少个志愿者变成这个点还差多少个志愿者到达标准,标准我们设为一个大常数U。看起来好像没有区别,但是事实上我们从源点出U,经过每一天相当于经过了U - a[i]的限制,流量会减少,我们需要用志愿者来使她满流出去,所以对于一个L到R的志愿者,我们建立一条L 到 R + 1,费用为W的边即可,相当于这个志愿者填上了L 到 R的空缺。

真是神奇啊

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e5 + ;
const int maxm = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int U = 1e5 + ;
const int mod = 1e9 + ;
int N,M,K;
struct MCMF{
struct Edge{
int from,to,cap,flow,nxt;
LL cost;
Edge() {}
Edge(int x,int y,int z,int u,LL v,int n){
from = x; to = y; cap = z; flow = u; cost = v; nxt = n;
}
}edge[maxm];
int E,n,head[maxn];
int inq[maxn],d[maxn],p[maxn],a[maxn];
inline void init(int _n){
n = _n;E = ;
memset(head,-,sizeof(head));
}
inline void addEdge(int f,int t,int c,LL w){
edge[E] = Edge(f,t,c,,w,head[f]);
head[f] = E++;
edge[E] = Edge(t,f,,,-w,head[t]);
head[t] = E++;
}
bool spfa(int s,int t,int &flow,LL &cost){
for(int i = ; i <= n ; i ++) d[i] = INF;
memset(inq,,sizeof(inq));
d[s] = ;inq[s] = ;p[s] = ;a[s] = INF;
queue<int>Q; Q.push(s);
while(!Q.empty()){
int u = Q.front(); Q.pop(); inq[u] = ;
for(int i = head[u]; ~i; i = edge[i].nxt){
Edge &e = edge[i];
if(e.cap <= e.flow || d[e.to] <= d[u] + e.cost) continue;
d[e.to] = d[u] + e.cost;
p[e.to] = i;
a[e.to] = min(a[u],e.cap - e.flow);
if(!inq[e.to]){
Q.push(e.to);
inq[e.to] = ;
}
}
}
if(d[t] == INF) return false;
flow += a[t];
cost += (LL)d[t] * (LL)a[t];
for(int u = t; u != s; u = edge[p[u]].from){
edge[p[u]].flow += a[t];
edge[p[u] ^ ].flow -= a[t];
}
return true;
} int mcmf(int s,int t,LL &cost){
int flow = ;
cost = ;
while(spfa(s,t,flow,cost));
return flow;
}
}g; int main()
{
Sca2(N,M);
int s = ,t = N + ;
g.init(t + ); g.addEdge(s,,U,);
For(i,,N){
LL x; Scl(x);
g.addEdge(i,i + ,U - x,);
}
while(M--){
int l,r; LL c;
Sca2(l,r); Scl(c);
g.addEdge(l,r + ,INF,c);
}
LL cost = ; g.mcmf(s,t,cost);
Prl(cost);
#ifdef VSCode
system("pause");
#endif
return ;
}

bzoj1061 建图 + 最小费用流的更多相关文章

  1. POJ 2195 一人一房 最小费用流 建图 水题

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 21010   Accepted: 10614 Desc ...

  2. [NOI2008][bzoj1061] 志愿者招募 [费用流+巧妙的建图]

    题面 传送门 思路 引入:网络流? 看到这道题,第一想法是用一个dp来完成决策 但是,显然这道题的数据并不允许我们进行dp,尤其是有10000种志愿者的情况下 那么我们就要想别的办法来解决: 贪心?这 ...

  3. 【BZOJ-1570】BlueMary的旅行 分层建图 + 最大流

    1570: [JSOI2008]Blue Mary的旅行 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 388  Solved: 212[Submit ...

  4. 【BZOJ-4289】Tax 最短路 + 技巧建图

    4289: PA2012 Tax Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 168  Solved: 69[Submit][Status][Dis ...

  5. CF467D Fedor and Essay 建图DFS

      Codeforces Round #267 (Div. 2) CF#267D D - Fedor and Essay D. Fedor and Essay time limit per test ...

  6. UVa 3487 & 蜜汁建图

    题意: 有两家公司都想向政府申请某些资源的使用权,并且他们都提供了一些申请列表,列表中含有申请费用和资源种类,同一家公司的申请列表之间不含有重复的资源.政府只可以完整地接受和拒绝谋一份申请列表,问政府 ...

  7. POJ 2226 最小点覆盖(经典建图)

    Muddy Fields Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8881   Accepted: 3300 Desc ...

  8. HDU 5669 线段树优化建图+分层图最短路

    用线段树维护建图,即把用线段树把每个区间都标号了,Tree1中子节点有到达父节点的单向边,Tree2中父节点有到达子节点的单向边. 每次将源插入Tree1,汇插入Tree2,中间用临时节点相连.那么T ...

  9. 【BZOJ-2879】美食节 最小费用最大流 + 动态建图

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1366  Solved: 737[Submit][Status] ...

随机推荐

  1. JS实现控制HTML5背景音乐播放暂停

    首先在网页中嵌入背景音乐,html5代码为: <script src="http://wuover.qiniudn.com/jquery.js"></script ...

  2. rsync 服务器搭建遇到的问题

    问题一: @ERROR: chroot failed rsync error: error starting client-server protocol (code 5) at main.c(152 ...

  3. nginx-添加禁止访问规则

    location ~* /application/(admin|index)/static/.*$ { allow all; } location ~* /(applicaion|addos|coe| ...

  4. P1914 一串字母

    P1914 题目背景 某蒟蒻迷上了“小书童”,有一天登陆时忘记密码了(他没绑定邮箱or手机),于是便把问题抛给了神犇你. 题目描述 蒟蒻虽然忘记密码,但他还记得密码是由一串字母组成.且密码是由一串字母 ...

  5. [SDOI2013] 直径

    传送门:>HERE< 题意:给出一颗树,求出被所有的直径都经过的边的数量 解题思路: 先求出任意一条直径并记录节点. 然后依次枚举直径上的每一个节点,判断从当前节点延伸出去的非直径的一条路 ...

  6. PIGS POJ - 1149(水最大流)

    题意: 有M个猪圈,每个猪圈里初始时有若干头猪.一开始所有猪圈都是关闭的.依次来了N个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪.每个顾客分别都有他能够买的数量的上限.每个顾客走后,他打开 ...

  7. IDEA @Contract annotation

    IDEA @Contract annotation ----------------------------------- http://www.jetbrains.com/help/idea/con ...

  8. MT【285】含参数函数绝对值的最大值

    (浙江2013高考压轴题)已知$a\in R$,函数$f(x)=x^3-3x^2+3ax-3a+3$(2)当$x\in[0,2]$时,求$|f(x)|$的最大值. 分析:由题意$f^{'}(x)=3x ...

  9. python的生成器与迭代器和可迭代对象

    来简单的说下python中的生成器和可迭代对象以及迭代器的问题.只是简单地记录一下并不涉及太深入的内容. 首先来说一下什么是生成器,先看下面的代码: #_*_ coding:utf-8 _*_ res ...

  10. Python的快排应有的样子

    快排算法 ​ 简单来说就是定一个位置然后,然后把比它小的数放左边,比他大的数放右边,这显然是一个递归的定义,根据这个思路很容易可以写出快排的代码 ​ 快排是我学ACM路上第一个让我记住的代码,印象很深 ...