题面

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

​ 这一题一看就是网络流, 但是要怎么构图呢? 考虑到途中的一些因素, 首先, 每一种志愿者控制的区间范围为\(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. linux 安装mysql8.0

    linux下安装mysql8.0 下载mysql $ wget http://mirrors.ustc.edu.cn/mysql-ftp/Downloads/MySQL-8.0/mysql-8.0.4 ...

  2. Redis简介及应用场景

    一丶Redis介绍 Redis是一个开源的 key—value型 单线程 数据库,支持string.list.set.zset和hash类型数据. 默认端口:6379 默认数据库数量:16 二.优点: ...

  3. NavicatForOracle无法连接数据库,报错ORA-28547

    因为换了新项目,要用到oracle数据库,但是用Navicat连接oracle不像连接MySql那样简单,连接的时候总是报ORA-28547,最后搜了一下解决方案发现是install client没有 ...

  4. 线程基础的一些理解(一)(java)

     一.多线程的基本概念 线程是指进程中的一个执行场景,也就是执行流程,所以我们首先要聊一聊进程,以及进程和线程的关系 1.什么是进程? 一个进程对应一个应用程序,就像我们在windows系统中启动Wo ...

  5. linux_shell_字符串

    字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号. 但是单引号和双引号是有区别的: 单引号: 单引号里的任何 ...

  6. js同时获取多个同name的input框的值

    demo代码 <!doctype html> <html ng-app="a3_4"> <head> <title>表头排序< ...

  7. 对象属性键值[key]属性问题

    1,obj[key]此时key代表是循环中的一个变量. var obj = {key:3,key1:1,key2:2,key3:3,toSting:4}; for (key in obj) { con ...

  8. apicloud 消息推送与接收

    待解决的问题,如下: 在使用apicloud 的时候我们,在开发用户登录的时候可能会遇到这样的问题,当有2个设备a,b同事使用的app的时候并且是同一个人登录,我们需要去做判断,即大家常说的单点登录. ...

  9. C3p0 的一个异常

    转的,异常如下: NewPooledConnection - com.mchange.v2.c3p0.impl.NewPooledConnection@1285252 closed by a clie ...

  10. 【mpvue】使用Mpvue撸一个简单的小程序

    一.快速创建一个mpvue项目   全局安装 vue-cli   (如果有就不需要装了) 创建一个基于mpvue-quickstart模板的新项目,记得选择安装vuex vue init mpvue/ ...