zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    SDNU 1311.Binomial Coeffcients
    SDNU 1306.兑数
    SDNU 1272.SL的秘密
    SDNU 1270.超超的难题
    XCode 自动化打包总结
    Xrun 将 app 转化为 IPA
    mac终端下运行shell脚本
    ios 检测应用程序升级问题
    在iis6.0公布asp.net mvc3网站
    IOS 中 NSArray
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5270881.html
Copyright © 2011-2022 走看看