bzoj1061 建图 + 最小费用流
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 建图 + 最小费用流的更多相关文章
- POJ 2195 一人一房 最小费用流 建图 水题
Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 21010 Accepted: 10614 Desc ...
- [NOI2008][bzoj1061] 志愿者招募 [费用流+巧妙的建图]
题面 传送门 思路 引入:网络流? 看到这道题,第一想法是用一个dp来完成决策 但是,显然这道题的数据并不允许我们进行dp,尤其是有10000种志愿者的情况下 那么我们就要想别的办法来解决: 贪心?这 ...
- 【BZOJ-1570】BlueMary的旅行 分层建图 + 最大流
1570: [JSOI2008]Blue Mary的旅行 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 388 Solved: 212[Submit ...
- 【BZOJ-4289】Tax 最短路 + 技巧建图
4289: PA2012 Tax Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 168 Solved: 69[Submit][Status][Dis ...
- CF467D Fedor and Essay 建图DFS
Codeforces Round #267 (Div. 2) CF#267D D - Fedor and Essay D. Fedor and Essay time limit per test ...
- UVa 3487 & 蜜汁建图
题意: 有两家公司都想向政府申请某些资源的使用权,并且他们都提供了一些申请列表,列表中含有申请费用和资源种类,同一家公司的申请列表之间不含有重复的资源.政府只可以完整地接受和拒绝谋一份申请列表,问政府 ...
- POJ 2226 最小点覆盖(经典建图)
Muddy Fields Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8881 Accepted: 3300 Desc ...
- HDU 5669 线段树优化建图+分层图最短路
用线段树维护建图,即把用线段树把每个区间都标号了,Tree1中子节点有到达父节点的单向边,Tree2中父节点有到达子节点的单向边. 每次将源插入Tree1,汇插入Tree2,中间用临时节点相连.那么T ...
- 【BZOJ-2879】美食节 最小费用最大流 + 动态建图
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1366 Solved: 737[Submit][Status] ...
随机推荐
- Nginx 减少关闭连接的time_wait端口数量
L:129
- Civil 3D 二次开发 创建AutoCAD对象—— 00 ——
不积跬步无以至千里,不积小流无以成江海.虽然创建一条直线.添加一个图层这样的小程序没有什么实际意义(内部命令很简单就可以完成),但对于初学二次开发的您来说,这可是一大步,这一步跨出去,您就跨进了二次开 ...
- P1578 奶牛浴场
P1578 奶牛浴场 题目描述 由于John建造了牛场围栏,激起了奶牛的愤怒,奶牛的产奶量急剧减少.为了讨好奶牛,John决定在牛场中建造一个大型浴场.但是John的奶牛有一个奇怪的习惯,每头奶牛都必 ...
- Python FAQ
1.在函数a中又定义了函数sum,内部函数sum可以引用外部函数a的参数n,不能这样写n=n+1,两个会出错,这样写s=s+n可以 解决: def a(): n = 1 def sum(): nonl ...
- bzoj 2733 : [HNOI2012]永无乡 (线段树合并)
Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...
- web 压力测试工具
最近有收到任务,测试新服务器的性能. 花了很长时间做搜索,也整理了一些资料.以下是收集到一些简单易用的分析工具.推荐给大家使用. WebBenchhttp://www.ha97.com/4623.ht ...
- The Python Challenge 谜题全解(持续更新)
Python Challenge(0-2) The Python Challengehttp://www.pythonchallenge.com/ 是个很有意思的网站,可以磨练使用python的技巧, ...
- 【原】本地仓库推送到远程仓库:fatal: refusing to merge unrelated histories
最近,在操作git的时候,遇到各种问题,下面总结一下. 最开始,我不是先把远程仓库拉取到本地 ,而是直接在本地先创建一个仓库,再git remote add添加远程仓库. 当然,gitee官方还是有操 ...
- webRequest封装
from requests.models import Response import requests import random import time class WebRequest(obje ...
- 买卖股票的最佳时机II
题目描述 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出股 ...