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
",ans*n1*lr);
else printf("-1
");
}
return 0;
}