BZOJ 3993 [SDOI2015]星际战争
题解:二分+网络流判定.
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<string> #include<cmath> #include<ctime> #include<algorithm> #include<map> #include<set> #include<queue> #include<iomanip> using namespace std; #define ll long long #define db double #define up(i,j,n) for(int i=j;i<=n;i++) #define pii pair<int,int> #define uint unsigned int #define FILE "dealing" #define eps 1e-4 int read(){ int x=0,f=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } template<class T> bool cmax(T& a,T b){return a<b?a=b,true:false;} template<class T> bool cmin(T& a,T b){return a>b?a=b,true:false;} const int maxn=60,limit=128,inf=1000000000,r=3,mod=1004535809; int n,m,S,T; int a[maxn][maxn]; int A[maxn],B[maxn]; db sum=0; // 护甲 攻击 struct node{ int y,next; db flow; }e[maxn*maxn*maxn]; int len=1,linkk[maxn<<1]; inline void insert(int x,int y,db flow){ e[++len].y=y; e[len].next=linkk[x]; linkk[x]=len; e[len].flow=flow; e[++len].y=x; e[len].next=linkk[y]; linkk[y]=len; e[len].flow=0; } inline int dcmp(db a){if(fabs(a)<eps)return 0;return a>0?1:-1;} int d[maxn<<1],q[maxn<<1],tail,head=0; bool makelevel(){ memset(d,-1,sizeof(d)); tail=head=0; q[++tail]=S;d[S]=1; while(++head<=tail){ int x=q[head]; for(int i=linkk[x];i;i=e[i].next){ if(d[e[i].y]==-1&&e[i].flow>eps) q[++tail]=e[i].y,d[e[i].y]=d[x]+1; } } return d[T]!=-1; } inline db makeflow(int x,db flow){ if(x==T||!dcmp(flow))return flow; db maxflow=0,dis=0; for(int i=linkk[x];i&&dcmp(flow-maxflow)>0;i=e[i].next){ if(e[i].flow>eps&&d[e[i].y]==d[x]+1) if(dis=makeflow(e[i].y,min(e[i].flow,flow-maxflow))){ e[i].flow-=dis; e[i^1].flow+=dis; maxflow+=dis; } } if(!dcmp(maxflow))d[x]=-1; return maxflow; } db dinic(){ db ans=0,d; while(makelevel()) while(dcmp(d=makeflow(S,1e9))) ans+=d; return ans; } bool check(db ti){ memset(linkk,0,sizeof(linkk)); len=1; up(i,1,m)insert(S,i,B[i]*ti); up(i,1,n)insert(i+m,T,A[i]); up(i,1,m)up(j,1,n)if(a[i][j])insert(i,m+j,1e9); db ans=dinic(); if(!dcmp(sum-ans))return 1; else return 0; } int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); n=read(),m=read();S=n+m+1,T=n+m+2; up(i,1,n)A[i]=read(),sum+=A[i]; up(i,1,m)B[i]=read(); up(i,1,m)up(j,1,n) a[i][j]=read(); db left=0,right=1e8,mid; while(right-left>eps){ mid=(left+right)/2; if(check(mid))right=mid; else left=mid; } printf("%.6lf\n",left); return 0; }