BZOJ3993 SDOI2015 星际战争 二分法+网络流
题意:有N个机器人护甲分别为ai,M个武器攻击力分别为bi/s,每个武器可以攻击的机器人不同,求摧毁所有机器人的最短时间,时间可以为小数
题解:实数上二分答案。好久没写网络流都不会开空间了……
#include <cmath> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define U 500000.0 #define eps 1e-6 #define S 0 #define T N+M+1 const int MAXN=50+2; const int MAXE=1000100+2; struct Hash{ int u; Hash *Next; }*Tab[2*MAXN],Mem[MAXE],*Cur[2*MAXN]; struct Edge{ int u; double c; }e[MAXE]; int N,M,cnt,d[2*MAXN]; double a[MAXN],b[MAXN],s; bool Can[MAXN][MAXN]; queue<int> q; void Insert(int u,int v,double c){ Mem[cnt].u=cnt,Mem[cnt].Next=Tab[u],e[cnt].u=v,e[cnt].c=c,Tab[u]=&Mem[cnt++]; Mem[cnt].u=cnt,Mem[cnt].Next=Tab[v],e[cnt].u=u,e[cnt].c=0,Tab[v]=&Mem[cnt++]; } bool BFS(int s,int t){ memset(d,-1,sizeof(d)); d[s]=0,q.push(s); int x; while(!q.empty()){ x=q.front(),q.pop(); for(Hash *p=Tab[x];p;p=p->Next){ if(e[p->u].c>eps && d[e[p->u].u]==-1) d[e[p->u].u]=d[x]+1,q.push(e[p->u].u); } } return d[t]>0; } double DFS(int x,double f,int t){ if(x==t) return f; double used=0,flow; for(Hash *p=Cur[x];p;p=p->Next) if(e[p->u].c>eps && d[e[p->u].u]==d[x]+1){ flow=DFS(e[p->u].u,min(e[p->u].c,f-used),t); e[p->u].c-=flow,e[p->u^1].c+=flow,used+=flow; if(e[p->u].c>eps) Cur[x]=p; if(f-used<eps) return f; } if(used==0) d[x]=-1; return used; } double Dinic(int s,int t){ double Ret=0; while(BFS(s,t)){ memcpy(Cur,Tab,sizeof(Cur)); Ret+=DFS(s,U,t); } return Ret; } int main(){ scanf("%d %d",&N,&M); for(int i=1;i<=N;i++) scanf("%lf",a+i),s+=a[i]; for(int i=1;i<=M;i++) scanf("%lf",b+i); for(int i=1;i<=M;i++) for(int j=1,t;j<=N;j++) scanf("%d",&t),Can[i][j]=t; double l=0,r=U,m; while(r-l>eps){ m=(l+r)/2,cnt=0; memset(Tab,0,sizeof(Tab)); for(int i=1;i<=M;i++){ Insert(S,i,b[i]*m); for(int j=1;j<=N;j++) if(Can[i][j]) Insert(i,M+j,U); } for(int i=1;i<=N;i++) Insert(M+i,T,a[i]); if(fabs(Dinic(S,T)-s)<eps) r=m; else l=m; } printf("%lf",m); return 0; }