BZOJ 3993 SDOI2015 星际战争
做法参见JSOI 冷冻波
(话说那个题目还需要写计算几何判断是否可以打到,这个题目直接给定0,1了QAQ)
二分+最大流判定即可
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #define eps 1e-6 using namespace std; const int maxn=112; const double oo=1e12; int n,m,S,T; double sum,ans; int a[maxn],b[maxn]; int map[maxn][maxn]; int h[maxn],cnt=1; int cur[maxn]; struct edge{ int to,next; double w; }G[200010]; queue<int>Q; int vis[maxn]; void add(int x,int y,double z){ ++cnt; G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt; ++cnt; G[cnt].to=x;G[cnt].next=h[y];G[cnt].w=0;h[y]=cnt; } void read(int &num){ num=0;char ch=getchar(); while(ch<'!')ch=getchar(); while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar(); } bool BFS(){ memset(vis,-1,sizeof(vis)); vis[S]=1;Q.push(S); while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=h[u];i;i=G[i].next){ int v=G[i].to; if(G[i].w>0&&vis[v]==-1){ vis[v]=vis[u]+1; Q.push(v); } } }return vis[T]!=-1; } double DFS(int x,double f){ if(x==T||fabs(f)<1e-10)return f; double w,used=0; for(int i=cur[x];i;i=G[i].next){ if(vis[G[i].to]==vis[x]+1){ w=f-used; w=DFS(G[i].to,min(G[i].w,w)); G[i].w-=w;G[i^1].w+=w; if(G[i].w>0)cur[x]=i; used+=w;if(fabs(used-f)<1e-10)return used; } } if(fabs(used)<1e-10)vis[x]=-1; return used; } void dinic(){ ans=0.0; while(BFS()){ for(int i=S;i<=T;++i)cur[i]=h[i]; ans+=DFS(S,oo); }return; } bool check(double k){ S=0;T=n+m+1;memset(h,0,sizeof(h));cnt=1; for(int i=1;i<=m;++i)add(S,i,k*b[i]); for(int i=1;i<=n;++i)add(i+m,T,a[i]); for(int i=1;i<=m;++i){ for(int j=1;j<=n;++j){ if(map[i][j])add(i,j+m,oo); } }dinic(); //printf("%.6lf\n",ans); return fabs(sum-ans)<1e-10; } int main(){ read(n);read(m); for(int i=1;i<=n;++i)read(a[i]),sum+=a[i]; for(int i=1;i<=m;++i)read(b[i]); for(int i=1;i<=m;++i){ for(int j=1;j<=n;++j){ read(map[i][j]); } } double L=0.0,R=5000000.0; while(R-L>eps){ double mid=(L+R)*0.5; if(check(mid))R=mid; else L=mid; } printf("%.6lf\n",L); return 0; }