joj 2662: 采购方案

CCST@JLU 要举办这次的程序设计大赛。为了节省开支,在各方面都得考虑仔细,比赛场地布置也不例外。在布置场地时,需要为每台电脑提供电源,由于电脑和电源的位置已经固定,所以要采购一些电源线来连接电脑和电源。kkk在采购时发现,购买相同数量的等长电源线总比购买长度不一的电源线要便宜很多(虽然电源线的价格和长度成正比,却不影响这个规律:)),所以kkk决定购买相同长度的电源线来布置场地。kkk想节省开支,你能帮助他么?

Input

第一行是测试用例的个数T. 每个测试用例的第一行是三个正整数n,m,(0 <= n <= 200,0 <= m <= 200,0 < r < 100)表示共有n台电脑与m个电源,以及在所有电源线都购买相同长度的情况下,单位长度的电源线需要r元。接下来n行,每行有m个正整数,dis[k](0 <= dis[k] <= 10000, 0 <= k < m),表示这台电脑与第k电源的距离。接下来一行有m个正整数,c[i](0 < c[i] < 5,0 <= i < m),表示第i个电源一共能为c[i]台电脑提供电源。

Output

如果电脑和电源位置不够合理,即无法为每台电脑都提供电源,输出-1. 否则,输出最便宜的购买电源线的总价格。

Input

1
2 2 1
1 3
2 2
1 1

Output

4

 

//

 

#include
#include
#include
using namespace std;
const int inf=(1<<30);
const int point_num=500;
int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面
int s0,t0,n;//源,汇和点数
int find_path(int p,int limit=0x3f3f3f3f)
{
    if(p==t0)   return limit;
    for(int i=0;i     if(dist[p]==dist[i]+1  &&  cap[p][i]>0)
    {
       int t=find_path(i,min(cap[p][i],limit));
       if(t<0)   return t;
       if(t>0)
       {
            cap[p][i]-=t;
            cap[i][p]+=t;
            return t;
       }
    }
    int label=n;
    for(int i=0;i0)  label=min(label,dist[i]+1);
    if(--gap[dist[p]]==0  ||  dist[s0]>=n )   return -1;
    ++gap[dist[p]=label];
    return 0;
}
int sap()
{
    //初始化s,t
    s0=0,t0=n-1;
    int t=0,maxflow=0;
    gap[0]=n;
    while((t=find_path(s0))>=0) maxflow+=t;
    return maxflow;
}
///..........................
int n1,n2,lr;
int d[point_num][point_num];
int in[point_num];
int solve(int limit)
{
    memset(cap,0,sizeof(cap));
    memset(dist,0,sizeof(dist));
    memset(gap,0,sizeof(gap));
    n=n1+n2+2;
    for(int i=1;i<=n1;i++) cap[0][i]=1;
    for(int i=1;i<=n2;i++) cap[n1+i][n-1]=in[i];
    for(int i=1;i<=n1;i++)
    {
        for(int j=1;j<=n2;j++)
        {
            if(d[i][j]<=limit)
            {
                cap[i][n1+j]=1;
            }
        }
    }
    int cnt=sap();
    if(cnt==n1) return 1;
    return 0;
}
int main()
{
    int ci;scanf("%d",&ci);
    while(ci--)
    {
        /**
        初始化
        memset(cap,0,sizeof(cap));
        memset(dist,0,sizeof(dist));
        memset(gap,0,sizeof(gap));
        */
        //n1 电脑  n2 电源
        scanf("%d%d%d",&n1,&n2,&lr);
        for(int i=1;i<=n1;i++) for(int j=1;j<=n2;j++) scanf("%d",&d[i][j]);
        for(int i=1;i<=n2;i++) scanf("%d",&in[i]);
        int l=0,r=11000;
        int ans=(1<<28);
        while(l         {
            int mid=(l+r)>>1;
            if(solve(mid))
            {
                r=mid;
                if(mid             }
            else l=mid+1;
        }
        if(ans!=(1<<28)) printf("%d\n",ans*n1*lr);
        else printf("-1\n");
    }
    return 0;
}

你可能感兴趣的:(acm_网络流)