题面

​ 又一次考试网络流爆零......

​ 这一题一看就是网络流, 但是要怎么构图呢? 考虑到途中的一些因素, 首先, 每一种志愿者控制的区间范围为\(S_{i}\)到\(T_{i}\), 所以, 我们要使得每种志愿者只能控制这段区间, 其他的不能够控制, 其次, 每个时间都有一个最小的值, 也就是这条边(我们将时间段看为一条边更加方便)有一个下界, 想到了什么, 上下界网络流, 每条边都要符合上界和下界的约束, 没有学过的可以戳一下.

​ 那么初始的构图也就出来了, 每个时间作为一条边, 那么由\(i\)向\(i + 1\)连一条边, 容量为\(INF - lower(i)\), 费用为0(由于人是控制一段区间的, 他在这段区间中的任意两个点流费用都为0, 可以看做这个人继续做事, 已经付钱了, 你得给我做完事才能走)(\(lower(i)\)代表时间\(i\)最少需要多少人, 其实这条边容量为\(INF\)没有问题, 假装上界为\(INF + lower(i)\)就可以了, 反正可以不停地流), 考虑到之前所说, 每个点只能约束自己的一段区间, 有点像循环流, 从\(S_{i}\)出发, 流到\(T_{i}\)就重新流, 但是这里由于\(T_{i}\)被看成了一条边, 所以我们需要在点\(T_{i} + 1\)往\(S_{i}\)连一条容量为\(INF\), 费用为\(c\)的边, 代表当前类\(i\)的志愿者控制且只能控制\(S_{i}\)到\(T_{i}\)这段时间.

​ 最终构图是这样的: 每个点\(i\)向\(i + 1\)连边, 每个\(T_{i} + 1\)向\(S_{i}\)连边, 注意在每个点\(i\)向\(i + 1\)连边时, 由于你是默认这条边流了一个下界的, 你每个点的流量不一定平衡, 记录一下每个点流入和流出的差, 对于一条下界为\(x\)的边i -> i + 1, 记\(delta[i]\)为点\(i\)流入与流出的差, 则\(delta[i] -= x\), \(delta[i + 1] += x\), 连完所有边后, 注意到每个点的\(delta\)不一定为0, 对于\(delta\)大于或者小于0的情况, 戳上面那个吧, 有详细的介绍, 最后跑一遍无源汇上下界最小费用可行流就可以了, 也就是在构出的有源汇的图中跑一遍最小费用最大流即可.

具体代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define N 2005
#define INF 1e9
using namespace std; int n, m, S, T, delta[N], head[N], cnt = 1, p[N], vis[N];
struct node
{
int from, to, next;
long long flow, cost;
} edge[100005];
long long a[N], d[N]; inline int read()
{
int x = 0, w = 1;
char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
} inline void add(int u, int v, long long w, long long cost)
{
edge[++cnt] = { u, v, head[u], w, cost }; head[u] = cnt;
edge[++cnt] = { v, u, head[v], 0, -cost }; head[v] = cnt;
} bool SPFA(long long &cost)
{
memset(d, 0x3f, sizeof(d)); memset(a, 0x3f, sizeof(a));
queue<int> q; q.push(S); d[S] = 0; vis[S] = 1;
while(!q.empty())
{
int u = q.front(); q.pop(); vis[u] = 0;
for(int i = head[u]; i; i = edge[i].next)
{
int v = edge[i].to;
if(d[v] > d[u] + edge[i].cost && edge[i].flow > 0)
{
d[v] = d[u] + edge[i].cost; a[v] = min(a[u], edge[i].flow);
p[v] = i; if(!vis[v]) { vis[v] = 1; q.push(v); }
}
}
}
if(d[T] == d[0]) return 0;
cost += (a[T] * d[T]);
for(int i = T; i != S; i = edge[p[i]].from)
{
edge[p[i]].flow -= a[T]; edge[p[i] ^ 1].flow += a[T];
}
return 1;
} int main()
{
n = read(); m = read();
S = n + 2; T = S + 1;
for(int i = 1; i <= n; i++) { int x = read(); add(i, i + 1, INF, 0); delta[i] -= x; delta[i + 1] += x; }
for(int i = 1; i <= m; i++)
{
int u = read(), v = read(), c = read();
add(v + 1, u, INF, c);
}
for(int i = 1; i <= n + 1; i++)
{
if(delta[i] < 0) add(i, T, -delta[i], 0);
if(delta[i] > 0) add(S, i, delta[i], 0);
}
long long cost = 0;
while(SPFA(cost));
printf("%lld\n", cost);
return 0;
}

[luogu3980] 志愿者招募的更多相关文章

  1. BZOJ 1061: [Noi2008]志愿者招募

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 4064  Solved: 2476[Submit][Stat ...

  2. BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记】

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3975  Solved: 2421[Submit][Stat ...

  3. BZOJ-1061 志愿者招募 线性规划转最小费用最大流+数学模型 建模

    本来一眼建模,以为傻逼题,然后发现自己傻逼...根本没想到神奇的数学模型..... 1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 ...

  4. [BZOJ1061][Noi2008]志愿者招募

    [BZOJ1061][Noi2008]志愿者招募 试题描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿 ...

  5. bzoj 1061 志愿者招募(最小费用最大流)

    [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3792  Solved: 2314[Submit][Status][Di ...

  6. 【BZOJ】【1061】【NOI2008】志愿者招募

    网络流/费用流 OrzOrzOrz,这题太神了不会捉. 题解:https://www.byvoid.com/blog/noi-2008-employee/ 这道题正确的解法是构造网络,求网络最小费用最 ...

  7. BZOJ 1061: [Noi2008]志愿者招募 费用流

    1061: [Noi2008]志愿者招募 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1061 Description 申奥成功后,布布 ...

  8. bzoj1061: [Noi2008]志愿者招募

    线性规划与费用流.http://www.cnblogs.com/iiyiyi/p/5616080.html.数组范围开错了!!!然后2.31-1=0x7fffffff!=0x7f7f7f7f. 开始以 ...

  9. NOI2008 志愿者招募

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1859  Solved: 1169[Submit][Stat ...

随机推荐

  1. 【Java基础】8、java中的native方法

    native是与C++联合开发的时候用的!java自己开发不用的! 使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用.这些函 ...

  2. Java JDBC MySQL

    一.驱动 下载地址:https://dev.mysql.com/downloads/connector/j/ 二.数据库连接配置 jdbc:mysql://address:port/database? ...

  3. javascript中常见错误类型

    js中控制台报错主分两大类: 第一类:语法错误,这一类错误在javascript预解析的过程中如果遇到,则会导致整个js文件都无法执行. 另一类:统称为异常,这一类的错误会导致在错误出现的那一行之后的 ...

  4. Hadoop大数据初入门----haddop伪分布式安装

    一.hadoop解决了什么问题 hdfs 解决了海量数据的分布式存储,高可靠,易扩展,高吞吐量mapreduce 解决了海量数据的分析处理,通用性强,易开发,健壮性 yarn 解决了资源管理调度 二. ...

  5. 数据表自增Id获取时IDENTITY的正确使用方式

    在SQLServer中很多表主键会设置为自增列,有的业务需求需要知道新插入的自增Id是多少,一般我们会用SELECT @@IDENTITY来获取,可由于@@IDENTITY是个全局变量作用据较大,所以 ...

  6. SQLServer 学习笔记之超详细基础SQL语句 Part 6

    Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 5------------------- 28 聚合函数 --求平均分 ...

  7. java截取电脑全屏

    通过java代码截取电脑屏幕全屏代码如下: import java.awt.AWTException; import java.awt.Dimension; import java.awt.Recta ...

  8. Net Core通用主机项目报错 程序不包含适合于入口点的静态Main

    Net Core通用主机的介绍: https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/host/generic-host?view=as ...

  9. 在 Azure 中创建通用 VM 的托管映像

    可以从在存储帐户中存储为托管磁盘或非托管磁盘的通用 VM 中创建托管映像资源. 然后可以使用该映像创建多个 VM. 使用 Sysprep 通用化 Windows VM Sysprep 将删除所有个人帐 ...

  10. Saltstack安装配置过程

    一.安装配置 1.服务器配置情况 三台服务器,均需要关闭iptables和selinux(否则salt执行指令无效) master: 192.168.60.139 centos slave: 192. ...