King's Pilots

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5644

Description

The military parade will last for n days. There is a aerobatic flight shows everyday during the parade. On the ith day , Pi pilots are required. But the pilots are not willing to work continually without an extra salary for even two days , because they are extremely tired.

There are m Holiday formulations in this country. For each formulation j , that is: when a pilot works on a day , if you pay him Sj dollars he is willing to come back Tj days after that day.

For example , If a pilot work on the rth day , and Tj==1 then he will return to work on r+1th day

At the very beginning there are k pilots , but of course you can hire more pilots. However , training new pilots require P days and for each new pilot you need pay him Q dollars. (Which means you can only use new pilots on Pth day or later)

Now our great king needs you to plan all these things. There must be enough pilots everyday and the cost must be minimized. Please tell the king what is the lowest cost;

The N - 1 round, the next person of the person who is out in the last round counts off, and the person who report number n−1 is out.

And the last man is survivor. Do you know the label of the survivor?

Input

The first line contains a number T(T≤5), the number of testcases.

For each testcase, the first line contains a number n(n≤200)

On the second line , there are n numbers Pi(1≤i≤n) indicating the number of pilots needed on that day

On the third line , 3 numbers , m(1≤m≤5),P,Q

On the following m lines , each line has two numbers: Si , Ti

all input data x satisfy x∈[0,200]

Output

For each testcase, print a single number. The minimum cost.

If there is no solution , just put No solution

Sample Input

1

5 10

1 3 5 10 6

1 3 5

2 2

Sample Output

48

Hint

题意

有n天,每天需要p[i]个人,你一开始雇佣了k个人

你从第p天开始可以再花Q元雇佣一个人。

然后这些人只会工作一天。

但是有m种政策,可以使得这些人在休息t[i]天后只用花s[i]元就可以再让这些工人工作了。

题解:

费用流。

建图的话建两层。

第一层假装没有那m种政策,然后无脑建图就好了。

S向1连容量为k,花费为0的边。

每个点向T连容量为P[i],花费为0的边。

每个点i向i+1连容量为inf,花费为0的边。

然后P天后的,连容量为inf,花费为q的边。

第二层连政策。

S向每个点连容量为P[i],花费为0的边。

每个点向T[i]天后的第一层的点连容量为inf,花费为S[i]

每个点i向i+1连容量为inf,花费为0的边。

一层维护工作,一层维护政策。

然后check是否满流就好了。

代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10000;
const int MAXM = 100000;
const int INF = 0x3f3f3f3f;
struct Edge
{
int to, next, cap, flow, cost;
int x, y;
} edge[MAXM],HH[MAXN],MM[MAXN];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N, M;
char map[MAXN][MAXN];
void init()
{
N = MAXN;
tol = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int cap, int cost)//左端点,右端点,容量,花费
{
edge[tol]. to = v;
edge[tol]. cap = cap;
edge[tol]. cost = cost;
edge[tol]. flow = 0;
edge[tol]. next = head[u];
head[u] = tol++;
edge[tol]. to = u;
edge[tol]. cap = 0;
edge[tol]. cost = -cost;
edge[tol]. flow = 0;
edge[tol]. next = head[v];
head[v] = tol++;
}
bool spfa(int s, int t)
{
queue<int>q;
for(int i = 0; i < N; i++)
{
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[s] = 0;
vis[s] = true;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
for(int i = head[u]; i != -1; i = edge[i]. next)
{
int v = edge[i]. to;
if(edge[i]. cap > edge[i]. flow &&
dis[v] > dis[u] + edge[i]. cost )
{
dis[v] = dis[u] + edge[i]. cost;
pre[v] = i;
if(!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
if(pre[t] == -1) return false;
else return true;
}
//返回的是最大流, cost存的是最小费用
int minCostMaxflow(int s, int t, int &cost)
{
int flow = 0;
cost = 0;
while(spfa(s,t))
{
int Min = INF;
for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
{
if(Min > edge[i]. cap - edge[i]. flow)
Min = edge[i]. cap - edge[i]. flow;
}
for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
{
edge[i]. flow += Min;
edge[i^1]. flow -= Min;
cost += edge[i]. cost * Min;
}
flow += Min;
}
return flow;
}
const int inf = 1e9;
int P[205],p,q,S[205],T[205];
void solve()
{
init();
int m,n,k,sum=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&P[i]),sum+=P[i];
scanf("%d%d%d",&m,&p,&q);
for(int i=1;i<=m;i++)
scanf("%d%d",&S[i],&T[i]);
int st=5000,ed=5001;
for(int i=1;i<=n;i++)
{
addedge(st,i,P[i],0);
addedge(n+i,ed,P[i],0);
}
addedge(st,n+1,k,0);
for(int i=p;i<=n;i++)
addedge(st,n+i,inf,q);
for(int i=1;i<n;i++)
addedge(i,i+1,inf,0);
for(int i=1;i<n;i++)
addedge(n+i,n+i+1,inf,0);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(i+T[j]<=n)
addedge(i,n+i+T[j],inf,S[j]);
}
int ans1=0,ans2=0;
ans1=minCostMaxflow(st,ed,ans2);
if(ans1==sum)printf("%d\n",ans2);
else printf("No solution\n");
}
int main()
{
int t;
scanf("%d",&t);
while(t--)solve();
return 0;
}

HDU 5644 King's Pilots 费用流的更多相关文章

  1. HDU 3667 Transportation(网络流之费用流)

    题目地址:HDU 3667 这题的建图真是巧妙...为了保证流量正好达到k.须要让每一次增广到的流量都是1,这就须要把每一条边的流量都是1才行.可是每条边的流量并非1,该怎么办呢.这个时候能够拆边,反 ...

  2. 【进阶——最小费用最大流】hdu 1533 Going Home (费用流)Pacific Northwest 2004

    题意: 给一个n*m的矩阵,其中由k个人和k个房子,给每个人匹配一个不同的房子,要求所有人走过的曼哈顿距离之和最短. 输入: 多组输入数据. 每组输入数据第一行是两个整型n, m,表示矩阵的长和宽. ...

  3. HDU 3488--Tour(KM or 费用流)

    因为每个点只能经过一次 所以考虑拆点 这题有坑,有重边.. KM算法 把一个点拆成入点和出点 入点在X部,出点在Y步. 如果u,v之间有路径,就在X部的u点连接Y部的v点 求完美匹配. 当完美匹配的时 ...

  4. HDU - 5406 CRB and Apple (费用流)

    题意:对于给定的物品,求两个在高度上单调不递增,权值上单调不递减的序列,使二者长度之和最大. 分析:可以用费用流求解,因为要求长度和最大,视作从源点出发的流量为2的费用流,建负权边,每个物品只能取一次 ...

  5. HDU 5644 King's Pliot【费用流】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5644 题意: 每天都有p[i]个飞行员进行阅兵,飞行员只工作一天. m个休假公式,花费tt[i]元让 ...

  6. HDU 5644 (费用流)

    Problem King's Pilots (HDU 5644) 题目大意 举办一次持续n天的飞行表演,第i天需要Pi个飞行员.共有m种休假计划,每个飞行员表演1次后,需要休假Si天,并提供Ti报酬来 ...

  7. hdu 1853 Cyclic Tour 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 There are N cities in our country, and M one-way ...

  8. Going Home HDU - 1533 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...

  9. Tour HDU - 3488 有向环最小权值覆盖 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=3488 给一个无源汇的,带有边权的有向图 让你找出一个最小的哈密顿回路 可以用KM算法写,但是费用流也行 思路 1 ...

随机推荐

  1. vim 颜色主题设置

    先看看vim编辑器提供的色彩配置方案: 首先进入vim的color目录(/usr/share/vim/vim74/colors,不同的系统目录不同,建议在-/建立.vim目录,然后在些目录里建立对应的 ...

  2. 【BubbleCup X】D. Exploration plan

    这个题首先一眼能看出二分答案…… 毕竟连可爱的边界都给你了. 下面就是怎么check 首先预处理跑一遍floyed,预处理出最短路. 用网络流判断能否达到即可. #include<bits/st ...

  3. ECMAScript 6 Promise 对象

    一.Promise的含义 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上说,Promise是一个对象,从它可以获取异步操作的消息. 1. ...

  4. (总结)MySQL自带的性能压力测试工具mysqlslap详解

    PS:今天一同事问我有木有比较靠谱的mysql压力测试工具可用.其实mysql自带就有一个叫mysqlslap的压力测试工具,还是模拟的不错的.下面举例说说.mysqlslap是从5.1.4版开始的一 ...

  5. 进度条算法 progressBar

    ; ;var maxNum=int.MaxValue; progressBar.Maximum =maxNum; progressBar.Minimum = ; progressBar.Value = ...

  6. Oracle常用sql语句(二)之组函数、多表查询

    DML(数据操纵语言) INSERT .UPDATE. DELETE 插入操作:INSERT: 语法: INSERT INTO 表名(列名1,列名2 ...)VALUES(列值1,列值2...); 注 ...

  7. /boot/grub/grub.conf 内容诠释

    linux的启动配置文件GRUB启动时会在 /boot/grub 中寻找一个名字为grub.conf的配置文件,如果找不到此配置文件则不进入菜单模式而直接进入命令行模式. grub.conf是一个纯文 ...

  8. leetcode 之Median of Two Sorted Arrays(五)

    找两个排好序的数组的中间值,实际上可以扩展为寻找第k大的数组值. 参考下面的思路,非常的清晰: 代码: double findMedianofTwoSortArrays(int A[], int B[ ...

  9. appium---【Mac】Appium-Doctor提示WARN:“ opencv4nodejs cannot be found”解决方案

    报错提示: AppiumDoctor  ✖. opencv4nodejs cannot be found 如下截图: 解决方案: 第一步:安装cmake并配置环境变量 1.打开terminal执行:c ...

  10. day4 装饰器深入解析

    Python装饰器 装饰器是在不修改源码给代码添加功能的常用方法.@是装饰的标志.我们知道,在给代码增加功能的时候,要遵循开放封闭的原则,不能随便更改原码,因此装饰器的功能就显示出来了,只需要在函数前 ...