LGP3324题解
一眼网络流,鉴定为纯纯的板子。
先二分一个答案,设为 \(k\)。
原点向每个激光武器连 \(k\times B_i\) 流量的边,每个机器人向汇点连 \(A_i\) 流量的边。
激光武器能攻击到机器人则连一条流量正无穷的边。
然后没了。。。
#include<cstdio>
typedef double db;
const int M=105;
int n,m,sum,ege,A[M],B[M],h[M],d[M],cur[M];int L,R,q[M];bool mp[M][M];
struct Edge{
int v,nx;db flow;
}e[M*M<<2];
inline db min(const db&a,const db&b){
return a>b?b:a;
}
inline void Add(const int&u,const int&v,const db&flow){
e[++ege]=(Edge){v,h[u],flow};h[u]=ege;
e[++ege]=(Edge){u,h[v],0};h[v]=ege;
}
inline bool BFS(){
for(int i=0;i<=n+m+1;++i)d[i]=0;d[q[L=R=1]=0]=1;
while(L<=R){
const int&u=q[L++];
for(int v,E=cur[u]=h[u];E;E=e[E].nx)if(!d[v=e[E].v]&&e[E].flow){
d[q[++R]=v]=d[u]+1;if(v==n+m+1)return true;
}
}
return false;
}
inline db DFS(const int&u,const db&flow){
if(u==n+m+1)return flow;
db sur(flow);
for(int v,&E=cur[u];E;E=e[E].nx)if(e[E].flow&&d[v=e[E].v]==d[u]+1){
const db&F=DFS(v,min(sur,e[E].flow));sur-=F;e[E].flow-=F;e[E^1].flow+=F;
if(!F)d[v]=0;if(!sur)return flow;
}
return flow-sur;
}
inline db Dinic(){
db ans(0);while(BFS())while(const db&F=DFS(0,1145141923))ans+=F;return ans;
}
inline bool check(const db&k){
ege=1;for(int i=0;i<=n+m+1;++i)h[i]=0;
for(int i=1;i<=n;++i)Add(0,i,A[i]*k);for(int i=1;i<=m;++i)Add(n+i,n+m+1,B[i]);
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(mp[i][j])Add(i,n+j,1145141923);return Dinic()==sum;
}
signed main(){
scanf("%d%d",&m,&n);for(int i=1;i<=m;++i)scanf("%d",B+i),sum+=B[i];for(int i=1;i<=n;++i)scanf("%d",A+i);
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)scanf("%d",mp[i]+j);
db L(0),R(50000),mid;while(L+1e-5<R)if(check(mid=(L+R)/2))R=mid;else L=mid;printf("%.4lf",L);
}