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. python进阶之关键字和运算符触发魔法方法

    前言 python有众多的魔法方法,它们会在满足某种条件下触发执行,掌握好魔法方法的使用,可以加快程序的运行效率,同时减少逻辑调用. 关键字与魔法方法 python的一些魔法方法是关键字触发的,即py ...

  2. centos7下vi的用法

    vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...

  3. 机顶盒 gettimeofday()获取毫秒溢出

    最近在写代码的时候遇见了一个bug,在获取当前时间戳的毫秒时,我自己测试的时候总是OK的,但是测试那边总是测不对,之前一直以为是因为我存储的类型的不对,从long long类型从lld改成llu,然后 ...

  4. Kiggle:Digit Recognizer

    题目链接:Kiggle:Digit Recognizer Each image is 28 pixels in height and 28 pixels in width, for a total o ...

  5. 20165301 预备作业二:学习基础和C语言基础调查

    <做中学>读后感及C语言学习调查 读<做中学>有感 娄老师在文章中多次提到「做中学(Learning By Doing)」的概念,并通过娄老师自己的减肥经历.五笔练习经历.乒乓 ...

  6. csu 1749: Soldiers ' Training(贪心)

    1749: Soldiers ' Training Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 37  Solved: 18[Submit][Stat ...

  7. Weex Workshop 挑战赛,等你来战!

    一个颠覆性的移动开发方式,一个匠心打造的跨平台移动开发工具,一个后App时代的生产力解放者—Weex,针对App Native开发频繁发版和多端研发的痛点,H5开发的页面稳定性.性能体验等问题,提供了 ...

  8. 摄像机distortion vector、project matrix、camera matrix

    关于标定后图像如何校正:http://wiki.ros.org/image_pipeline/CameraInfo ros distortion vector 参数顺序:http://docs.ros ...

  9. C语言小程序之整除

    看到有人要求用C语言写这样一个小程序,就拿来温习一下 需求:输出从1到2015这2015个自然数中,能被4或5整除,但不能被30整除的数,并计算有多少个数.   #include<stdio.h ...

  10. IEEEXtreme 10.0 - Inti Sets

    这是 meelo 原创的 IEEEXtreme极限编程大赛题解 Xtreme 10.0 - Inti Sets 题目来源 第10届IEEE极限编程大赛 https://www.hackerrank.c ...