• 省赛练习2 Doctor NiGONiGO’s multicore CPU 最大费用最大流


    Doctor NiGONiGO’s multi-core CPU

    Time Limit 2000ms

    Memory Limit 65536K

    description

    Doctor NiGONiGO has developed a new kind of multi-core CPU, it works as follow. There are q (1 < q ≤ 50) identical cores in the CPU, and there are p (0 < p ≤ 200) jobs need to be done. Each job should run in some core and need only one unit time. The cores in the CPU can work simultaneously but each core can implement only one job at a time. When a job completed, it will incur a deferral cost. Job i has a deferral cost c(i, j) (0 ≤ c(i, j) ≤ 1000000), where j is the completion time of the job (1 ≤ j ≤ p) because any job done in the time later than p obviously not the optimal solution). Here we assume that c(i, j) is a monotonically no decreasing function of j. Now you are asked to find the schedule which have the minimum overall deferral cost.
    							

    input

    An integer T indicated the number of test cases. 
    For each test case:
    There are two integers q, p in first line. 
    And Following is p lines, each line contain p integer, the jth integer of the ith line is the deferral cost c(i, j).
    							

    output

    For each test case, output a singer integer, which is the minimum total deferral cost of the Problem.
    							

    sample_input

    1
    2 4
    89 145 181 269
    4 86 158 164
    60 143 157 165
    4 45 109 207
    							

    sample_output

    254
    ------------------------------------------------------------------------------------------------------------

    源点S到工作Pi连一条容量为1费用为0的边,工作Pi到时间Tj连一条容量为1费用为c(i,j)的边,时间Tj到汇点连一条容量为q费用为0的边。

    最大费用最大流即是答案。

    由于同一件工作的花费是递增的,所以至多用(p/q+1)时间就可以完成所有工作,因此时间(p/q+1)之后的边可以删去。

    ------------------------------------------------------------------------------------------------------------

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    const int OO=1e9;//无穷大
    const int maxm=11111111;//边的最大数量,为原图的两倍
    const int maxn=222222;//点的最大数量
    
    int node,src,dest,edge;//node节点数,src源点,dest汇点,edge边数
    int head[maxn],p[maxn],dis[maxn],q[maxn],vis[maxn];//head链表头,p记录可行流上节点对应的反向边,dis计算距离
    
    struct edgenode
    {
        int to;//边的指向
        int flow;//边的容量
        int cost;//边的费用
        int next;//链表的下一条边
    } edges[maxm];
    
    void prepare(int _node,int _src,int _dest);
    void addedge(int u,int v,int f,int c);
    bool spfa();
    
    inline int min(int a,int b)
    {
        return a<b?a:b;
    }
    
    inline void prepare(int _node,int _src,int _dest)
    {
        node=_node;
        src=_src;
        dest=_dest;
        for (int i=0; i<node; i++)
        {
            head[i]=-1;
            vis[i]=false;
        }
        edge=0;
    }
    
    void addedge(int u,int v,int f,int c)
    {
        edges[edge].flow=f;
        edges[edge].cost=c;
        edges[edge].to=v;
        edges[edge].next=head[u];
        head[u]=edge++;
        edges[edge].flow=0;
        edges[edge].cost=-c;
        edges[edge].to=u;
        edges[edge].next=head[v];
        head[v]=edge++;
    }
    
    bool spfa()
    {
        int i,u,v,l,r=0,tmp;
        for (i=0; i<node; i++) dis[i]=OO;
        dis[q[r++]=src]=0;
        p[src]=p[dest]=-1;
        for (l=0; l!=r; ((++l>=maxn)?l=0:1))
        {
            for (i=head[u=q[l]],vis[u]=false; i!=-1; i=edges[i].next)
            {
                if (edges[i].flow&&dis[v=edges[i].to]>(tmp=dis[u]+edges[i].cost))
                {
                    dis[v]=tmp;
                    p[v]=i^1;
                    if (vis[v]) continue;
                    vis[q[r++]=v]=true;
                    if (r>=maxn) r=0;
                }
            }
        }
        return p[dest]>=0;
    }
    
    int spfaflow()
    {
        int i,ret=0,delta;
        while (spfa())
        {
            //按记录原路返回求流量
    
            for (i=p[dest],delta=OO; i>=0; i=p[edges[i].to])
            {
                delta=min(delta,edges[i^1].flow);
            }
            for (int i=p[dest]; i>=0; i=p[edges[i].to])
            {
                edges[i].flow+=delta;
                edges[i^1].flow-=delta;
            }
            ret+=delta*dis[dest];
        }
        return ret;
    }
    
    int q_cpu;
    int p_jobs;
    int cost[222][222];
    int T;
    int ls;
    
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d%d",&q_cpu,&p_jobs);
            ls=p_jobs/q_cpu+1;
            prepare(p_jobs*2+2,0,p_jobs*2+1);
            for (int i=1;i<=p_jobs;i++)
            {
                addedge(src,i,1,0);
                for (int j=1;j<=p_jobs;j++)
                {
                    scanf("%d",&cost[i][j]);
                    if (j<=ls) addedge(i,j+p_jobs,1,cost[i][j]);
                }
            }
            for (int i=1;i<=p_jobs;i++)
            {
                if (i<=ls) addedge(i+p_jobs,dest,q_cpu,0);
            }
            int ans=spfaflow();
            printf("%d\n",ans);
        }
        return 0;
    }
    







  • 相关阅读:
    Tensorflow基础教程11:常用模块 tf.data :数据集的构建与预处理
    Tensorflow基础教程10:常用模块 TensorBoard:训练过程可视化
    Tensorflow基础教程9:常用模块 tf.train.Checkpoint 之变量的保存与恢复
    Tensorflow基础教程8:自定义层、损失函数和评估指标
    OC原理之多线程中的锁(一)
    OC原理之多线程(二)
    OC原理之多线程(一)
    OC原理之RunLoop的运行逻辑
    OC原理RunLoop(一)
    前端模块化:CommonJS,AMD,CMD,ES6
  • 原文地址:https://www.cnblogs.com/cyendra/p/3038431.html
Copyright © 2020-2023  润新知