题目大意:有n个机器人和m个激光武器,每个武器有一个威力和能打的集合,同一时刻只能打一个机器人,问最少多久可以全灭
二分答案+网络流= =
注意二分上界
#include <cstdio> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define M 110 #define S 0 #define T (M-1) #define EPS 1e-7 #define INF 1e10 using namespace std; int n,m; int a[M],b[M]; namespace Max_Flow{ struct abcd{ int to,next; double f; }table[1001001]; int head[M],tot=1; int dpt[M]; void Add(int x,int y,double z) { table[++tot].to=y; table[tot].f=z; table[tot].next=head[x]; head[x]=tot; } void Link(int x,int y,double z) { Add(x,y,z); Add(y,x,0); } bool BFS() { static int q[M]; int i,r=0,h=0; memset(dpt,-1,sizeof dpt); q[++r]=S;dpt[S]=1; while(r!=h) { int x=q[++h]; for(i=head[x];i;i=table[i].next) if(table[i].f>EPS&&!~dpt[table[i].to]) { dpt[table[i].to]=dpt[x]+1; q[++r]=table[i].to; if(table[i].to==T) return true; } } return false; } double Dinic(int x,double flow) { int i;double left=flow; if(x==T) return flow; for(i=head[x];i&&left>EPS;i=table[i].next) if(table[i].f>EPS&&dpt[table[i].to]==dpt[x]+1) { double temp=Dinic(table[i].to,min(left,table[i].f)); left-=temp; table[i].f-=temp; table[i^1].f+=temp; } if(left>EPS) dpt[x]=-1; return flow-left; } bool Check(double x) { int i; for(i=2;i<=tot;i+=2) table[i].f+=table[i^1].f,table[i^1].f=0; for(i=head[S];i;i=table[i].next) table[i].f=b[table[i].to-n]*x; while( BFS() ) Dinic(S,INF); for(i=head[T];i;i=table[i].next) if(table[i^1].f>EPS) return false; return true; } } double Bisection() { using namespace Max_Flow; double l=0,r=5e6; while(r-l>EPS) { double mid=(l+r)/2; if( Check(mid) ) r=mid; else l=mid; } return (l+r)/2; } int main() { using namespace Max_Flow; int i,j,x; cin>>n>>m; for(i=1;i<=n;i++) { scanf("%d",&a[i]); Link(i,T,a[i]); } for(i=1;i<=m;i++) { scanf("%d",&b[i]); Link(S,n+i,0); } for(i=1;i<=m;i++) for(j=1;j<=n;j++) { scanf("%d",&x); if(x==1) Link(n+i,j,INF); } cout<<fixed<<setprecision(10)<<Bisection()<<endl; } /* S 0 T (M-1) 1~n 每个巨型机器人 n+1~n+m 每个激光武器 */
时间: 2024-11-08 12:26:46