3993: [SDOI2015]星际战争
题目:传送门
题解:
洛谷AC了,但是因为bzoj的spj有问题所以暂时没A
一道老题目了,二分时间然后网络流判断。
每次st-->武器连时间*攻击力
武器-->机器人 流量无限
机器人-->ed 流量为血量值
精度有点gou...
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define eps 1e-7 7 #define inf 999999999.0 8 using namespace std; 9 struct node 10 { 11 int x,y,next,other; 12 double c; 13 }a[2100000];int len,last[2100000]; 14 void ins(int x,int y,double c) 15 { 16 int k1,k2; 17 k1=++len; 18 a[len].x=x;a[len].y=y;a[len].c=c; 19 a[len].next=last[x];last[x]=len; 20 21 k2=++len; 22 a[len].x=y;a[len].y=x;a[len].c=0; 23 a[len].next=last[y];last[y]=len; 24 25 a[k1].other=k2; 26 a[k2].other=k1; 27 } 28 int st,ed,n,m,head,tail; 29 int list[2100000],h[2100000]; 30 bool bt_h() 31 { 32 memset(h,0,sizeof(h));h[st]=1; 33 list[1]=st;head=1;tail=2; 34 while(head!=tail) 35 { 36 int x=list[head]; 37 for(int k=last[x];k;k=a[k].next) 38 { 39 int y=a[k].y; 40 if(!h[y] && a[k].c>0) 41 { 42 h[y]=h[x]+1; 43 list[tail++]=y; 44 } 45 } 46 head++; 47 } 48 if(h[ed])return true; 49 return false; 50 } 51 double find_flow(int x,double flow) 52 { 53 if(x==ed)return flow; 54 double s=0,t; 55 for(int k=last[x];k;k=a[k].next) 56 { 57 int y=a[k].y; 58 if(h[y]==h[x]+1 && a[k].c>0 && s<flow) 59 { 60 s+=t=find_flow(y,min(a[k].c,flow-s)); 61 a[k].c-=t;a[a[k].other].c+=t; 62 } 63 } 64 if(s==0)h[x]=0; 65 return s; 66 } 67 double A[51],B[51]; 68 int map[51][51]; 69 bool check(double x) 70 { 71 double sum=0.0,ans=0.0; 72 len=0;memset(last,0,sizeof(last)); 73 for(int i=1;i<=m;i++)ins(st,i,x*B[i]); 74 for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)if(map[i][j]==1)ins(i,j+m,inf); 75 for(int i=1;i<=n;i++)ins(i+m,ed,A[i]),sum+=A[i]; 76 while(bt_h())ans+=find_flow(st,inf); 77 if(abs(ans-sum)<=eps)return true; 78 return false; 79 } 80 int main() 81 { 82 scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lf",&A[i]);for(int i=1;i<=m;i++)scanf("%lf",&B[i]); 83 st=n+m+1,ed=st+1; 84 for(int i=1;i<=m;i++) 85 for(int j=1;j<=n;j++) 86 scanf("%d",&map[i][j]); 87 double l=0.0,r=10000000.0,ans=0.0; 88 while(l<=r) 89 { 90 double mid=(l+r)/2; 91 if(check(mid))ans=mid,r=mid-eps; 92 else l=mid+eps; 93 } 94 printf("%.6lf ",ans); 95 return 0; 96 }