BZOJ3993: [SDOI2015]星际战争
【传送门:BZOJ3993】
简要题意:
给出n个机器人,防御值为A[i],有m个武器,每个武器每秒会有B[i]的伤害,武器能打到一些机器人,求出最小的时间消灭所有机器人
题解:
二分+网络流
二分时间(假设为ans),然后st连向武器i,流量为B[i]*ans,如果武器能打到机器人,则武器连向机器人,流量无限,然后将机器人连向ed,流量为A[i]
就输入问题,WA了半版!
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define eps 1e-7 using namespace std; struct node { int x,y,next,other; double c; }a[210000];int len,last[3100]; void ins(int x,int y,double c) { int k1=++len,k2=++len; a[k1].x=x;a[k1].y=y;a[k1].c=c; a[k1].next=last[x];last[x]=k1; a[k2].x=y;a[k2].y=x;a[k2].c=0; a[k2].next=last[y];last[y]=k2; a[k1].other=k2; a[k2].other=k1; } int h[3100],list[3100],st,ed; bool bt_h() { memset(h,0,sizeof(h)); h[st]=1; int head=1,tail=2; list[1]=st; while(head!=tail) { int x=list[head]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(h[y]==0&&a[k].c>eps) { h[y]=h[x]+1; list[tail++]=y; } } head++; } if(h[ed]==0) return false; else return true; } double findflow(int x,double f) { if(x==ed) return f; double s=0,t; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(h[y]==(h[x]+1)&&a[k].c>eps&&f-s>eps) { t=findflow(y,min(a[k].c,f-s)); s+=t; a[k].c-=t;a[a[k].other].c+=t; } } if(abs(s)<=eps) h[x]=0; return s; } double A[51],B[51]; int map[51][51]; double cc;int n,m; bool check(double x) { len=0;memset(last,0,sizeof(last)); for(int i=1;i<=m;i++) ins(st,i,B[i]*x); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) if(map[i][j]==1) ins(i,j+m,999999999); for(int i=1;i<=n;i++) ins(i+m,ed,A[i]); double ans=0.0; while(bt_h()==true) { ans+=findflow(st,999999999.9); } if(abs(ans-cc)<=eps) return true; else return false; } int main() { scanf("%d%d",&n,&m);st=0;ed=n+m+1; for(int i=1;i<=n;i++){scanf("%lf",&A[i]);cc+=A[i];} for(int i=1;i<=m;i++) scanf("%lf",&B[i]); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) scanf("%d",&map[i][j]); double l=0.0,r=999999999.9,ans; while(l<=r) { double mid=(l+r)/2; if(check(mid)==true) { r=mid-0.0000001; ans=mid; } else l=mid+0.0000001; } printf("%.6lf\n",ans); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚