https://www.lydsy.com/JudgeOnline/problem.php?id=3993
二分时间t 看规定时间内能否消灭全部机器人 sss(大源点)向ss(小源点)连权值为sum(a[1]+a[2]+...+a[n])的边 ss向m个炮塔连b[i]*t的边 m个炮塔向n个机器人连b[i]*t的边 n个机器人向汇点连a[i]的边
using namespace std;
const double N=1000000000.0;
const double eps=1e-8;;
const int maxn=1e2+10;
const int maxm=1e5+10;
struct node
{
double w;
int v,next;
};
queue <int> que;
node edge[maxm];
double a[maxn],b[maxn];
double sum;
int e[maxn][maxn];
int first[maxn],dis[maxn],gap[maxn],cur[maxn],pre[maxn];
int n,m,num,sss,ss,eee;
void addedge(int u,int v,double w)
{
edge[num].v=v;
edge[num].w=w;
edge[num].next=first[u];
first[u]=num++;
edge[num].v=u;
edge[num].w=0;
edge[num].next=first[v];
first[v]=num++;
}
void bfs()
{
int i,u,v;
while(!que.empty()) que.pop();
memset(dis,-1,sizeof(dis));
memset(gap,0,sizeof(gap));
que.push(eee);
dis[eee]=0;
gap[0]++;
while(!que.empty()){
u=que.front();
que.pop();
for(i=first[u];i!=-1;i=edge[i].next){
v=edge[i].v;
if(dis[v]==-1){
que.push(v);
dis[v]=dis[u]+1;
gap[dis[v]]++;
}
}
}
}
double isap()
{
double w,flow,ans;
int j,u,v,minn;
bfs();
memcpy(cur,first,sizeof(first));
memset(pre,-1,sizeof(pre));
u=sss,flow=N,ans=0.0;
while(dis[sss]<num){
int &i=cur[u];
for(;i!=-1;i=edge[i].next){
v=edge[i].v,w=edge[i].w;
if(dis[v]+1==dis[u]&&w>0.0){
pre[v]=i;
u=v,flow=min(flow,w);
if(u==eee){
while(u!=sss){
edge[pre[u]].w-=flow;
edge[pre[u]^1].w+=flow;
u=edge[pre[u]^1].v;
}
//printf("*%.2f*\n",flow);
ans+=flow,flow=N;
}
break;
}
}
if(i==-1){
if(--gap[dis[u]]==0) break;
cur[u]=first[u];
minn=num-1;
for(j=first[u];j!=-1;j=edge[j].next){
v=edge[j].v,w=edge[j].w;
if(w>0.0){
minn=min(minn,dis[v]);
}
}
dis[u]=minn+1;
gap[dis[u]]++;
if(u!=sss) u=edge[pre[u]^1].v;
}
}
return ans;
}
bool judge(double lim)
{
double res;
int i,j;
sss=n+m+1,ss=n+m+2,eee=n+m+3;
memset(first,-1,sizeof(first));
num=0;
addedge(sss,ss,sum*lim);
for(i=1;i<=m;i++){
addedge(ss,i,b[i]*lim);
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(e[i][j]){
addedge(i,m+j,b[i]*lim);
}
}
}
for(i=m+1;i<=m+n;i++){
addedge(i,eee,a[i-m]);
}
num=n+m+3;
res=isap();
//printf("%.2f\n",res);
if(res>=sum) return 1;
else return 0;
}
double solve()
{
double res,l,r,mid;
l=0.0,r=100000.0;
while(r-l>eps){
mid=(l+r)/2.0;
if(judge(mid)) r=mid,res=mid;
else l=mid;
}
//judge(1.3);
return res;
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
sum=0.0;
for(i=1;i<=n;i++){
scanf("%lf",&a[i]);
sum+=a[i];
}
for(i=1;i<=m;i++){
scanf("%lf",&b[i]);
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
scanf("%d",&e[i][j]);
}
}
printf("%.6f\n",solve());
return 0;
}