• HDU 5644 King's Pilots 费用流


    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
    ",ans2);
        else printf("No solution
    ");
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)solve();
        return 0;
    }
  • 相关阅读:
    Java通过反射加载的类,变量无法注入
    jmeter http并发测试时报错
    spring 自定义注解
    cmd 和powershell 用git 显示乱码
    centos6.8上安装部署 jhipster-registry
    tcpdf最新版 6.2版
    微信Oauth2.0鉴权 40029 问题
    微信支付学习记录1
    win10 localhost 解析为 ipv6地址 ::1 的解决办法
    PHPExcel 导出时乱码
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5270881.html
Copyright © 2020-2023  润新知