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);
}
posted @ 2022-07-16 16:14  Prean  阅读(12)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};