BZOJ3993 星际战争 题解(二分+最大流)

来源:互联网 发布:程序员培训全日制吗 编辑:程序博客网 时间:2024/04/30 03:45

星际战争

【问题描述】

3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战。在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai。当一个巨型机器人的装甲值减少到0或者以下时,这个巨型机器人就被摧毁了。X军团有M个激光武器,其中第i个激光武器每秒可以削减一个巨型机器人Bi的装甲值。激光武器的攻击是连续的。这种激光武器非常奇怪,一个激光武器只能攻击一些特定的敌人。Y军团看到自己的巨型机器人被X军团一个一个消灭,他们急需下达更多的指令。为了这个目标,Y军团需要知道X军团最少需要用多长时间才能将Y军团的所有巨型机器人摧毁。但是他们不会计算这个问题,因此向你求助。

【数据规模和约定】

对于30%的数据,1<=N, M<=5;

对于全部的数据,1<=N,M<=50,1<=Ai<=105,1<=Bi<=1000,输入数据保证X军团一定能摧毁Y军团的所有巨型机器人。

建立一个网络,源点S,汇点T。S连到所有的激光节点,激光节点连到能攻击到的巨人节点,所有巨人节点连到T。

二分时间t,将所有S到激光节点的最大流量设置为输出的攻击总量Bi*t,巨人节点和T之间的流量设置为Ai。

对这个图跑最大流,如果最大流等于所有装甲值之和,说明能在规定时间内能打掉所有巨人,更新上界。否则更新下界。

注意精度问题,float的精度不够。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include<queue>#include<cmath>#define INF 2333333using namespace std;int cnt=0;const double eps=1e-6;vector<int> tab[4000];int n,m;int dis[4000];int cur[4000];double a[55],b[55];int S,T;double sum;struct edge{int u,v;double cap;edge(int u_,int v_,double cap_){u=u_;v=v_;cap=cap_;} edge(){}}eg[8000];void addedge(int u,int v,double c){eg[cnt]=edge(u,v,c);tab[u].push_back(cnt++);eg[cnt]=edge(v,u,0);tab[v].push_back(cnt++); }void modify(double t){int i=0;for(int j=1;j<=n;i+=2,++j){eg[i].cap=a[j];eg[i^1].cap=0.0;}for(int j=1;j<=m;i+=2,++j){eg[i].cap=t*b[j];eg[i^1].cap=0.0;}for(;i<cnt;++i){if(i&1)eg[i].cap=0.0;else eg[i].cap=INF;}}queue<int> q;bool bfs(){q.push(S);for(int i=S;i<=T;++i)dis[i]=INF;dis[S]=0;while(!q.empty()){int now = q.front();q.pop();int sz=tab[now].size();for(int i=0;i<sz;++i){edge& e=eg[tab[now][i]];if(dis[e.v]>dis[now]+1&&e.cap>eps){dis[e.v]=dis[now]+1;q.push(e.v);}}}return dis[T]<INF;}double dfs(int now,double flow){if(now==T)return flow;int sz=tab[now].size();for(int& i=cur[now];i<sz;++i){edge& e=eg[tab[now][i]];if(dis[now]+1==dis[e.v]&&e.cap>eps){double f=dfs(e.v,(double)min(flow,e.cap));if(f>eps){e.cap-=f;eg[tab[now][i]^1].cap+=f;return f;}}}return 0;}double dinic(){double ans=0,flow=0;while(bfs()){memset(cur,0,sizeof(cur));while((flow=dfs(S,INF))>eps)ans+=flow;}return ans;}bool can(double t){modify(t);double flow=dinic();return fabs(flow-sum)<eps;}double bsearch(double l,double r){if(r-l<eps)return (l+r)/2.0;double mid = (l+r)/2.0;if(can(mid))return bsearch(l,mid);else return bsearch(mid,r);}int main(){//freopen("war.in","r",stdin);//freopen("war.out","w",stdout);scanf("%d%d",&n,&m);S=1;T=n+m+2;for(int i=1;i<=n;++i){scanf("%lf",&a[i]);sum+=a[i]; addedge(m+i+1,T,a[i]);}for(int i=1;i<=m;++i){scanf("%lf",&b[i]);addedge(S,i+1,0.0);}for(int i=1;i<=m;++i){for(int j=1;j<=n;++j){int c;scanf("%d",&c);if(c==1)addedge(i+1,m+j+1,INF);}}printf("%.6lf\n",bsearch(0.0,100010.0));return 0;}


0 0
原创粉丝点击