由于时间可能是小数,所以不能直接跑。
先二分答案为 t t t。
S S S 向每个激光武器 i i i 连一条容量为 b i × t b_i imes t bi×t 的边,表示这个激光武器最多能输出多少。
然后每个机器人向 T T T 连一条容量为 a i a_i ai 的边,表示这个机器人至少需要这么多攻击才能被摧毁。
接着每个激光武器向每个它能攻击的机器人连一条容量为 inf inf inf 的边。
然后跑最大流看流量等不等于所有机器人的血量之和。
因为时间是小数,所以二分的时候时间和机器人血量先乘上个 1 0 3 10^3 103,最后输出的时候再除就好了。
代码:
#include<bits/stdc++.h>
#define N 55
#define ll long long
#define LNF 0x7fffffffffffffff
using namespace std;
int n,m,s,t;
int a[N],b[N];
int cnt=1,head[N<<1],cur[N<<1],to[(N*N+(N<<1))<<1],nxt[(N*N+(N<<1))<<1];
int stcnt,sthead[N<<1];
int num[N<<1];
ll sum;
ll c[(N*N+(N<<1))<<1],stc[(N*N+(N<<1))<<1];
queue<int>q;
void adde(int u,int v,ll ci)
{
to[++cnt]=v;
c[cnt]=ci;
nxt[cnt]=head[u];
head[u]=cnt;
}
bool bfs()
{
memcpy(cur,head,sizeof(cur));
memset(num,-1,sizeof(num));
num[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];
if(c[i]&&num[v]==-1)
{
num[v]=num[u]+1;
q.push(v);
}
}
}
return num[t]!=-1;
}
ll dfs(int u,ll minflow)
{
if(!minflow||u==t) return minflow;
ll preflow=0,nowflow;
for(int i=cur[u];i;i=nxt[i])
{
cur[u]=i;
int v=to[i];
if(num[v]==num[u]+1&&(nowflow=dfs(v,min(minflow-preflow,c[i]))))
{
preflow+=nowflow;
c[i]-=nowflow;
c[i^1]+=nowflow;
if(!(minflow-preflow)) break;
}
}
return preflow;
}
ll dinic()
{
ll maxflow=0;
while(bfs())
maxflow+=dfs(s,LNF);
return maxflow;
}
bool check(int x)
{
cnt=stcnt;
memcpy(head,sthead,sizeof(head));
memcpy(c,stc,sizeof(c));
for(int i=1;i<=m;i++)
{
adde(s,1+i,1ll*b[i]*x);
adde(1+i,s,0);
}
return dinic()==sum;
}
int main()
{
scanf("%d%d",&n,&m);
s=1,t=1+m+n+1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]),a[i]*=1000;
sum+=a[i];
adde(1+m+i,t,a[i]);
adde(t,1+m+i,0);
}
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
int x;
scanf("%d",&x);
if(x)
{
adde(1+i,1+m+j,LNF);
adde(1+m+j,1+i,0);
}
}
}
stcnt=cnt;
memcpy(sthead,head,sizeof(sthead));
memcpy(stc,c,sizeof(stc));
int l=0,r=1000000000,ans;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%lf
",1.0*ans/1000);
return 0;
}