zoukankan      html  css  js  c++  java
  • 省赛练习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;
    }
    







  • 相关阅读:
    Git常用命令
    更新CentOS内核
    VMware虚拟机安装Ubuntu系统步骤详解
    Ubuntu安装遇到的问题
    IOT OS and OTA
    gcc c asm,C程序内嵌汇编
    makefile and make tips
    RTEMS目录梳理Sparc
    关于FreeRTOS的信号量、队列
    FreeRTOS任务源码分析以及程序堆栈与任务堆栈的关系
  • 原文地址:https://www.cnblogs.com/cyendra/p/3038431.html
Copyright © 2011-2022 走看看